GNUnet 0.28.1-dev.2-13-g57ceb9dfb
 
Loading...
Searching...
No Matches
gnunet-communicator-tcp.c
Go to the documentation of this file.
1/*
2 This file is part of GNUnet
3 Copyright (C) 2010-2014, 2018, 2019, 2026 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
30#include "platform.h"
31#include "gnunet_common.h"
32#include "gnunet_util_lib.h"
33#include "gnunet_pils_service.h"
34#include "gnunet_core_service.h"
36#include "gnunet_protocols.h"
37#include "gnunet_signatures.h"
38#include "gnunet_constants.h"
39#include "gnunet_nat_service.h"
43
44/* Shorthand for Logging */
45#define LOG(kind, ...) GNUNET_log_from (kind, "communicator-tcp", __VA_ARGS__)
46
47
52#define NAT_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10)
53
58#define ADDRESS_VALIDITY_PERIOD \
59 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 4)
60
69#define DEFAULT_MAX_QUEUE_LENGTH 8
70
75#define BUF_SIZE (2 * 64 * 1024 + sizeof(struct TCPBox))
76
83#define TCP_QUEUE_GONE SIZE_MAX
84
88#define DEFAULT_REKEY_INTERVAL GNUNET_TIME_UNIT_DAYS
89
93#define PROTO_QUEUE_TIMEOUT GNUNET_TIME_UNIT_MINUTES
94
102#define FINISH_TIMEOUT GNUNET_TIME_relative_multiply ( \
103 GNUNET_TIME_UNIT_SECONDS, 5)
104
109#define REKEY_MAX_BYTES (1024LLU * 1024 * 400)
110
115#define INITIAL_KX_SIZE \
116 (sizeof(struct GNUNET_CRYPTO_EcdhePublicKey) \
117 + sizeof(struct TCPConfirmation))
118
122#define INITIAL_CORE_KX_SIZE \
123 (sizeof(struct EphemeralKeyMessage) \
124 + sizeof(struct PingMessage) \
125 + sizeof(struct PongMessage))
126
130#define COMMUNICATOR_ADDRESS_PREFIX "tcp"
131
135#define COMMUNICATOR_CONFIG_SECTION "communicator-tcp"
136
138
139
177
210
238
273
277struct TCPBox
278{
286
296
297 /* followed by as may bytes of payload as indicated in @e header,
298 excluding the TCPBox itself! */
299};
300
301
339
372
395
412
414
419{
420 /*
421 * Timeout task.
422 */
424
429
433 struct sockaddr *in;
434};
435
451
455struct Queue
456{
461
466
471
476
480 gcry_cipher_hd_t in_cipher;
481
485 gcry_cipher_hd_t out_cipher;
486
491
496
502
507
512
519
523 struct sockaddr *address;
524
530
536
540 socklen_t address_len;
541
546
551
555 unsigned long long bytes_in_queue;
556
561
566
570 char pread_buf[UINT16_MAX + 1 + sizeof(struct TCPBox)];
571
575 char pwrite_buf[UINT16_MAX + 1 + sizeof(struct TCPBox)];
576
581 size_t cread_off;
582
588
593 size_t pread_off;
594
600
605
613 unsigned int backpressure;
614
619
624
629
634
642
648
653
658
663
668
673
678
683
688
693
698
703
707 // TODO remove?
709
714};
715
716
722{
727
732
737
742
747
751 char write_buf[sizeof (struct TCPNATProbeMessage)];
752
756 size_t write_off;
757
762
766 struct sockaddr *address;
767
771 socklen_t address_len;
772
777
783
787 size_t ibuf_off;
788};
789
794{
798 struct sockaddr *addr_ipv4;
799
803 socklen_t addr_len_ipv4;
804
808 struct sockaddr *addr_ipv6;
809
813 socklen_t addr_len_ipv6;
814
815};
816
820struct Addresses
821{
825 struct Addresses *next;
826
830 struct Addresses *prev;
831
835 struct sockaddr *addr;
836
840 socklen_t addr_len;
841
842};
843
844
848static unsigned long long max_queue_length;
849
854
859
864
869
874
879
883static unsigned long long rekey_max_bytes;
884
889
893static const struct GNUNET_CONFIGURATION_Handle *cfg;
894
899
903static struct GNUNET_NAT_Handle *nat;
904
908static struct ProtoQueue *proto_head;
909
913static struct ProtoQueue *proto_tail;
914
919
923static struct Addresses *addrs_head;
924
928static struct Addresses *addrs_tail;
929
933static int addrs_lens;
934
939
944
948static int disable_v6;
949
953static unsigned int bind_port;
954
959
967static void
968listen_cb (void *cls);
969
970static void
980
981
982static void
991
992
1000static void
1002{
1003 struct ListenTask *lt = NULL;
1004 struct GNUNET_HashCode h_sock;
1005 int sockfd;
1006
1007 if (NULL != queue->listen_sock)
1008 {
1009 sockfd = GNUNET_NETWORK_get_fd (queue->listen_sock);
1010 GNUNET_CRYPTO_hash (&sockfd,
1011 sizeof(int),
1012 &h_sock);
1013
1015 }
1016
1018 "Disconnecting queue for peer `%s'\n",
1019 GNUNET_i2s (&queue->target));
1020 if (NULL != queue->rekey_monotime_sc)
1021 {
1022 GNUNET_PEERSTORE_store_cancel (queue->rekey_monotime_sc);
1023 queue->rekey_monotime_sc = NULL;
1024 }
1025 if (NULL != queue->handshake_monotime_sc)
1026 {
1027 GNUNET_PEERSTORE_store_cancel (queue->handshake_monotime_sc);
1028 queue->handshake_monotime_sc = NULL;
1029 }
1030 if (NULL != queue->handshake_ack_monotime_sc)
1031 {
1032 GNUNET_PEERSTORE_store_cancel (queue->handshake_ack_monotime_sc);
1033 queue->handshake_ack_monotime_sc = NULL;
1034 }
1035 if (NULL != queue->rekey_monotime_get)
1036 {
1037 GNUNET_PEERSTORE_iteration_stop (queue->rekey_monotime_get);
1038 queue->rekey_monotime_get = NULL;
1039 }
1040 if (NULL != queue->handshake_monotime_get)
1041 {
1042 GNUNET_PEERSTORE_iteration_stop (queue->handshake_monotime_get);
1043 queue->handshake_monotime_get = NULL;
1044 }
1045 if (NULL != queue->handshake_ack_monotime_get)
1046 {
1047 GNUNET_PEERSTORE_iteration_stop (queue->handshake_ack_monotime_get);
1048 queue->handshake_ack_monotime_get = NULL;
1049 }
1050 if (NULL != queue->qh)
1051 {
1053 queue->qh = NULL;
1054 }
1056 GNUNET_YES ==
1059 "# queues active",
1061 GNUNET_NO);
1062 if (NULL != queue->finish_task)
1063 {
1064 GNUNET_SCHEDULER_cancel (queue->finish_task);
1065 queue->finish_task = NULL;
1066 }
1067 if (NULL != queue->read_task)
1068 {
1069 GNUNET_SCHEDULER_cancel (queue->read_task);
1070 queue->read_task = NULL;
1071 }
1072 if (NULL != queue->write_task)
1073 {
1074 GNUNET_SCHEDULER_cancel (queue->write_task);
1075 queue->write_task = NULL;
1076 }
1078 {
1080 "closing socket failed\n");
1081 }
1082 gcry_cipher_close (queue->in_cipher);
1083 gcry_cipher_close (queue->out_cipher);
1084 GNUNET_free (queue->address);
1085 if (0 != queue->backpressure)
1086 queue->destroyed = GNUNET_YES;
1087 else
1089
1090 if (NULL == lt)
1091 return;
1092
1093 if ((! shutdown_running) && (NULL == lt->listen_task))
1094 {
1096 "add read net listen\n");
1099 lt->listen_sock,
1100 &listen_cb,
1101 lt);
1102 }
1103 else
1104 GNUNET_free (lt);
1105}
1106
1107
1116static void
1118 const void *buf,
1119 size_t buf_size,
1120 struct GNUNET_ShortHashCode *smac)
1121{
1122 struct GNUNET_HashCode mac;
1123
1124 GNUNET_CRYPTO_hmac (hmac_secret,
1125 buf,
1126 buf_size,
1127 &mac);
1128 /* truncate to `struct GNUNET_ShortHashCode` */
1129 memcpy (smac, &mac, sizeof(struct GNUNET_ShortHashCode));
1130 /* ratchet hmac key */
1131 GNUNET_CRYPTO_hash (hmac_secret,
1132 sizeof(struct GNUNET_HashCode),
1133 (struct GNUNET_HashCode*) hmac_secret);
1134}
1135
1136
1137static void
1138queue_write (void *cls);
1139
1140
1149static void
1151{
1152 struct Queue *queue = cls;
1153
1154 queue->finish_task = NULL;
1156 "Queue to %s did not flush its FINISH in time, tearing it down\n",
1157 GNUNET_i2s (&queue->target));
1159}
1160
1161
1168static void
1170{
1171 struct TCPFinish fin;
1172
1173 if (GNUNET_YES == queue->destroyed)
1174 return; /* socket is already gone, we only await backpressure draining */
1175 memset (&fin, 0, sizeof(fin));
1176 fin.header.size = htons (sizeof(fin));
1178 calculate_hmac (&queue->out_hmac, &fin, sizeof(fin), &fin.hmac);
1179 /* if there is any message left in pwrite_buf, we
1180 overwrite it (possibly dropping the last message
1181 from CORE hard here) */
1182 memcpy (queue->pwrite_buf, &fin, sizeof(fin));
1183 queue->pwrite_off = sizeof(fin);
1184 /* This flag will ensure that #queue_write() no longer
1185 notifies CORE about the possibility of sending
1186 more data, and that #queue_write() will call
1187 #queue_destroy() once the @c fin was fully written. */
1188 queue->finishing = GNUNET_YES;
1189 /* ... but #queue_write() only ever re-arms itself while it still has data
1190 buffered, and #mq_send() returns early for a finishing queue. So unless
1191 we arm the write task here, nothing writes the @c fin, #queue_destroy()
1192 is never reached, and transport is never told that this queue died: it
1193 keeps scheduling transmissions that #mq_send() silently drops, and CORE
1194 never learns about the disconnect. */
1195 if (NULL == queue->write_task)
1196 queue->write_task =
1198 queue->sock,
1199 &queue_write,
1200 queue);
1201 /* And if the peer is gone, the socket may never become writable at all. */
1202 if (NULL == queue->finish_task)
1205 queue);
1206}
1207
1208
1214static void
1215queue_read (void *cls);
1216
1217
1225static void
1226core_read_finished_cb (void *cls, int success)
1227{
1228 struct Queue *queue = cls;
1229 if (GNUNET_OK != success)
1231 "# messages lost in communicator API towards CORE",
1232 1,
1233 GNUNET_NO);
1234 if (NULL == queue)
1235 return;
1236
1238 "backpressure %u\n",
1239 queue->backpressure);
1240
1241 queue->backpressure--;
1242 /* handle deferred queue destruction */
1243 if ((queue->destroyed) && (0 == queue->backpressure))
1244 {
1246 return;
1247 }
1248 else if (GNUNET_YES != queue->destroyed)
1249 {
1250 queue->timeout =
1252 );
1253 /* possibly unchoke reading, now that CORE made progress */
1254 if (NULL == queue->read_task)
1255 queue->read_task =
1257 queue->timeout),
1258 queue->sock,
1259 &queue_read,
1260 queue);
1261 }
1262}
1263
1264
1274static void
1276 const void *plaintext,
1277 size_t plaintext_len)
1278{
1279 const struct GNUNET_MessageHeader *hdr = plaintext;
1280 int ret;
1281
1283 "pass message from %s to core\n",
1284 GNUNET_i2s (&queue->target));
1285
1286 if (ntohs (hdr->size) != plaintext_len)
1287 {
1288 /* NOTE: If we ever allow multiple CORE messages in one
1289 BOX, this will have to change! */
1290 GNUNET_break (0);
1291 return;
1292 }
1294 &queue->target,
1295 hdr,
1298 queue);
1300 "passed to core\n");
1301 if (GNUNET_OK == ret)
1302 queue->backpressure++;
1303 GNUNET_break (GNUNET_NO != ret); /* backpressure not working!? */
1304 if (GNUNET_SYSERR == ret)
1306 "# bytes lost due to CORE not running",
1307 plaintext_len,
1308 GNUNET_NO);
1309}
1310
1311
1321static void
1323 const struct GNUNET_PeerIdentity *pid,
1324 gcry_cipher_hd_t *cipher,
1325 struct GNUNET_CRYPTO_AuthKey *hmac_key)
1326{
1327 char key[256 / 8];
1328 char ctr[128 / 8];
1329
1330 GNUNET_assert (0 == gcry_cipher_open (cipher,
1331 GCRY_CIPHER_AES256 /* low level: go for speed */
1332 ,
1333 GCRY_CIPHER_MODE_CTR,
1334 0 /* flags */));
1337 key,
1338 sizeof(key),
1339 prk,
1340 GNUNET_CRYPTO_kdf_arg_string ("gnunet-communicator-tcp-key"))
1341 );
1342 GNUNET_assert (0 == gcry_cipher_setkey (*cipher, key, sizeof(key)));
1345 ctr,
1346 sizeof(ctr),
1347 prk,
1348 GNUNET_CRYPTO_kdf_arg_string ("gnunet-communicator-tcp-ctr"))
1349 );
1350 gcry_cipher_setctr (*cipher, ctr, sizeof(ctr));
1353 hmac_key,
1354 sizeof(struct GNUNET_HashCode),
1355 prk,
1356 GNUNET_CRYPTO_kdf_arg_string ("gnunet-communicator-hmac")));
1357}
1358
1359
1365static void
1366rekey_monotime_store_cb (void *cls, int success)
1367{
1368 struct Queue *queue = cls;
1369 if (GNUNET_OK != success)
1370 {
1372 "Failed to store rekey monotonic time in PEERSTORE!\n");
1373 }
1374 queue->rekey_monotime_sc = NULL;
1375 GNUNET_PEERSTORE_iteration_next (queue->rekey_monotime_get, 1);
1376}
1377
1378
1386static void
1388 const struct GNUNET_PEERSTORE_Record *record,
1389 const char *emsg)
1390{
1391 struct Queue *queue = cls;
1392 struct GNUNET_TIME_AbsoluteNBO *mtbe;
1393 struct GNUNET_TIME_Absolute mt;
1394 const struct GNUNET_PeerIdentity *pid;
1395 struct GNUNET_TIME_AbsoluteNBO *rekey_monotonic_time;
1396
1397 (void) emsg;
1398
1399 rekey_monotonic_time = &queue->rekey_monotonic_time;
1400 pid = &queue->target;
1401 if (NULL == record)
1402 {
1403 queue->rekey_monotime_get = NULL;
1404 return;
1405 }
1406 if (sizeof(*mtbe) != record->value_size)
1407 {
1408 GNUNET_PEERSTORE_iteration_next (queue->rekey_monotime_get, 1);
1409 GNUNET_break (0);
1410 return;
1411 }
1412 mtbe = record->value;
1413 mt = GNUNET_TIME_absolute_ntoh (*mtbe);
1415 queue->rekey_monotonic_time).abs_value_us)
1416 {
1418 "Queue from %s dropped, rekey monotime in the past\n",
1419 GNUNET_i2s (&queue->target));
1420 GNUNET_break (0);
1421 GNUNET_PEERSTORE_iteration_stop (queue->rekey_monotime_get);
1422 queue->rekey_monotime_get = NULL;
1423 // FIXME: Why should we try to gracefully finish here??
1425 return;
1426 }
1427 queue->rekey_monotime_sc = GNUNET_PEERSTORE_store (peerstore,
1428 "transport_tcp_communicator",
1429 pid,
1431 rekey_monotonic_time,
1432 sizeof(*
1433 rekey_monotonic_time),
1437 queue);
1438}
1439
1440
1447static void
1449 const struct GNUNET_CRYPTO_HpkeEncapsulation *c,
1450 struct Queue *queue)
1451{
1452 const struct GNUNET_PeerIdentity *my_identity;
1454 struct GNUNET_CRYPTO_HpkePrivateKey my_hpke_key;
1455 struct GNUNET_ShortHashCode k;
1456
1460
1461 eddsa_priv_to_hpke_key (my_private_key, &my_hpke_key);
1462
1464 c,
1465 &k);
1466 setup_cipher (&k, my_identity, &queue->in_cipher, &queue->in_hmac);
1467}
1468
1469
1476static void
1491
1492
1501static void
1502do_rekey (struct Queue *queue, const struct TCPRekey *rekey)
1503{
1504 const struct GNUNET_PeerIdentity *my_identity;
1505 struct TcpRekeySignature thp;
1506
1509
1511 thp.purpose.size = htonl (sizeof(thp));
1513 "do_rekey size %u\n",
1514 thp.purpose.size);
1515 thp.sender = queue->target;
1517 "sender %s\n",
1520 "sender %s\n",
1521 GNUNET_p2s (&queue->target.public_key));
1522 thp.receiver = *my_identity;
1524 "receiver %s\n",
1526 thp.ephemeral = rekey->ephemeral;
1528 "ephemeral %s\n",
1530 );
1531 thp.monotonic_time = rekey->monotonic_time;
1533 "time %s\n",
1536 GNUNET_assert (ntohl ((&thp)->purpose.size) == sizeof (*(&thp)));
1537 if (GNUNET_OK !=
1540 &thp,
1541 &rekey->sender_sig,
1542 &queue->target.public_key))
1543 {
1544 GNUNET_break (0);
1545 // FIXME Why should we try to gracefully finish here?
1547 return;
1548 }
1549 queue->rekey_monotonic_time = rekey->monotonic_time;
1550 queue->rekey_monotime_get = GNUNET_PEERSTORE_iteration_start (peerstore,
1551 "transport_tcp_communicator",
1552 &queue->target,
1554 &
1556 queue);
1557 gcry_cipher_close (queue->in_cipher);
1558 queue->rekeyed = GNUNET_YES;
1559 setup_in_cipher (&rekey->ephemeral, queue);
1560}
1561
1562
1568static void
1569handshake_ack_monotime_store_cb (void *cls, int success)
1570{
1571 struct Queue *queue = cls;
1572
1573 if (GNUNET_OK != success)
1574 {
1576 "Failed to store handshake ack monotonic time in PEERSTORE!\n");
1577 }
1578 queue->handshake_ack_monotime_sc = NULL;
1579 GNUNET_PEERSTORE_iteration_next (queue->handshake_ack_monotime_get, 1);
1580}
1581
1582
1590static void
1592 const struct GNUNET_PEERSTORE_Record *record,
1593 const char *emsg)
1594{
1595 struct Queue *queue = cls;
1596 struct GNUNET_TIME_AbsoluteNBO *mtbe;
1597 struct GNUNET_TIME_Absolute mt;
1598 const struct GNUNET_PeerIdentity *pid;
1599 struct GNUNET_TIME_AbsoluteNBO *handshake_ack_monotonic_time;
1600
1601 (void) emsg;
1602
1603 handshake_ack_monotonic_time = &queue->handshake_ack_monotonic_time;
1604 pid = &queue->target;
1605 if (NULL == record)
1606 {
1607 queue->handshake_ack_monotime_get = NULL;
1608 return;
1609 }
1610 if (sizeof(*mtbe) != record->value_size)
1611 {
1612 GNUNET_PEERSTORE_iteration_next (queue->handshake_ack_monotime_get, 1);
1613 GNUNET_break (0);
1614 return;
1615 }
1616 mtbe = record->value;
1617 mt = GNUNET_TIME_absolute_ntoh (*mtbe);
1619 queue->handshake_ack_monotonic_time).abs_value_us)
1620 {
1622 "Queue from %s dropped, handshake ack monotime in the past\n",
1623 GNUNET_i2s (&queue->target));
1624 GNUNET_break (0);
1625 GNUNET_PEERSTORE_iteration_stop (queue->handshake_ack_monotime_get);
1626 queue->handshake_ack_monotime_get = NULL;
1627 // FIXME: Why should we try to gracefully finish here?
1629 return;
1630 }
1631 queue->handshake_ack_monotime_sc =
1633 "transport_tcp_communicator",
1634 pid,
1636 handshake_ack_monotonic_time,
1637 sizeof(*handshake_ack_monotonic_time),
1641 queue);
1642}
1643
1644
1651static void
1653 struct Queue *queue)
1654{
1655 const struct GNUNET_PeerIdentity *my_identity;
1657 struct TCPConfirmationAck tca;
1658 struct TcpHandshakeAckSignature thas;
1659
1663
1665 "sending challenge\n");
1666
1667 tca.header.type = ntohs (
1669 tca.header.size = ntohs (sizeof(tca));
1670 tca.challenge = challenge;
1671 tca.sender = *my_identity;
1672 tca.monotonic_time =
1674 thas.purpose.purpose = htonl (
1676 thas.purpose.size = htonl (sizeof(thas));
1677 thas.sender = *my_identity;
1678 thas.receiver = queue->target;
1679 thas.monotonic_time = tca.monotonic_time;
1680 thas.challenge = tca.challenge;
1682 &thas,
1683 &tca.sender_sig);
1684 GNUNET_assert (0 ==
1685 gcry_cipher_encrypt (queue->out_cipher,
1686 &queue->cwrite_buf[queue->cwrite_off],
1687 sizeof(tca),
1688 &tca,
1689 sizeof(tca)));
1690 queue->cwrite_off += sizeof(tca);
1692 "sending challenge done\n");
1693}
1694
1695
1702static void
1704{
1705 setup_cipher (dh, &queue->target, &queue->out_cipher, &queue->out_hmac);
1707 queue->rekey_left_bytes =
1709}
1710
1711
1718static void
1720{
1721 const struct GNUNET_PeerIdentity *my_identity;
1723 struct TCPRekey rekey;
1724 struct TcpRekeySignature thp;
1725 struct GNUNET_ShortHashCode k;
1726
1730
1731 GNUNET_assert (0 == queue->pwrite_off);
1732 memset (&rekey, 0, sizeof(rekey));
1733 GNUNET_CRYPTO_eddsa_kem_encaps (&queue->target.public_key, &rekey.ephemeral,
1734 &k);
1736 rekey.header.size = ntohs (sizeof(rekey));
1737 rekey.monotonic_time =
1740 thp.purpose.size = htonl (sizeof(thp));
1742 "inject_rekey size %u\n",
1743 thp.purpose.size);
1744 thp.sender = *my_identity;
1746 "sender %s\n",
1748 thp.receiver = queue->target;
1750 "receiver %s\n",
1752 thp.ephemeral = rekey.ephemeral;
1754 "ephemeral %s\n",
1756 );
1757 thp.monotonic_time = rekey.monotonic_time;
1759 "time %s\n",
1763 &thp,
1764 &rekey.sender_sig);
1765 calculate_hmac (&queue->out_hmac, &rekey, sizeof(rekey), &rekey.hmac);
1766 /* Encrypt rekey message with 'old' cipher */
1767 GNUNET_assert (0 ==
1768 gcry_cipher_encrypt (queue->out_cipher,
1769 &queue->cwrite_buf[queue->cwrite_off],
1770 sizeof(rekey),
1771 &rekey,
1772 sizeof(rekey)));
1773 queue->cwrite_off += sizeof(rekey);
1774 /* Setup new cipher for successive messages */
1775 gcry_cipher_close (queue->out_cipher);
1776 setup_out_cipher (queue, &k);
1777}
1778
1779
1795static void
1796pending_reversal_key (const struct sockaddr *in,
1797 const struct GNUNET_PeerIdentity *target,
1798 struct GNUNET_HashCode *key)
1799{
1800 struct sockaddr_in v4;
1801 struct GNUNET_HashContext *hsh;
1802
1803 GNUNET_assert (AF_INET == in->sa_family);
1804 GNUNET_memcpy (&v4, in, sizeof(v4));
1805 v4.sin_port = 0;
1807 GNUNET_CRYPTO_hash_context_read (hsh, &v4, sizeof(v4));
1808 GNUNET_CRYPTO_hash_context_read (hsh, target, sizeof(*target));
1810}
1811
1812
1813static int
1815 const struct GNUNET_HashCode *key,
1816 void *value)
1817{
1818 struct PendingReversal *pending_reversal = value;
1819 (void) cls;
1820
1821 if (NULL != pending_reversal->timeout_task)
1822 {
1823 GNUNET_SCHEDULER_cancel (pending_reversal->timeout_task);
1824 pending_reversal->timeout_task = NULL;
1825 }
1828 key,
1829 pending_reversal));
1830 GNUNET_free (pending_reversal->in);
1831 GNUNET_free (pending_reversal);
1832 return GNUNET_OK;
1833}
1834
1835
1849static void
1850check_and_remove_pending_reversal (struct sockaddr *in, sa_family_t sa_family,
1851 const struct GNUNET_PeerIdentity *sender)
1852{
1853 if (AF_INET == sa_family)
1854 {
1855 struct PendingReversal *pending_reversal;
1856 struct GNUNET_HashCode key;
1857
1858 pending_reversal_key (in, sender, &key);
1860 &key);
1861 if (NULL != pending_reversal)
1862 {
1864 "Removing completed pending reversal for `%s' at `%s'\n",
1865 GNUNET_i2s (&pending_reversal->target),
1866 GNUNET_a2s (in, sizeof (struct sockaddr)));
1867 pending_reversals_delete_it (NULL, &key, pending_reversal);
1868 }
1869 }
1870}
1871
1872
1878static void
1880{
1881 if (NULL != pq->listen_sock)
1882 {
1884 pq->listen_sock = NULL;
1885 }
1886 if (NULL != pq->read_task)
1887 {
1889 pq->read_task = NULL;
1890 }
1891 if (NULL != pq->write_task)
1892 {
1894 pq->write_task = NULL;
1895 }
1896 /* NOTE: deliberately no #check_and_remove_pending_reversal() here. A proto
1897 queue is anonymous -- we have not completed the KX, so we do not know
1898 which peer this was. Dropping "the" pending reversal for the IP used to
1899 cancel the reversal of an unrelated peer that happens to sit behind the
1900 same NAT. A reversal that truly went nowhere expires on #NAT_TIMEOUT. */
1902 GNUNET_free (pq->address);
1904 GNUNET_free (pq);
1905}
1906
1907
1914static void
1916{
1917 struct ProtoQueue *pq = cls;
1918 ssize_t sent;
1919 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "In proto queue write\n");
1920 pq->write_task = NULL;
1921 if (0 != pq->write_off)
1922 {
1923 sent = GNUNET_NETWORK_socket_send (pq->sock,
1924 pq->write_buf,
1925 pq->write_off);
1927 "Sent %lu bytes to TCP queue\n", sent);
1928 if ((-1 == sent) && (EAGAIN != errno) && (EINTR != errno))
1929 {
1931 free_proto_queue (pq);
1932 return;
1933 }
1934 if (sent > 0)
1935 {
1936 size_t usent = (size_t) sent;
1937 pq->write_off -= usent;
1938 memmove (pq->write_buf,
1939 &pq->write_buf[usent],
1940 pq->write_off);
1941 }
1942 }
1943 /* do we care to write more? */
1944 if ((0 < pq->write_off))
1945 pq->write_task =
1947 pq->sock,
1949 pq);
1950}
1951
1952
1959static void
1960queue_write (void *cls)
1961{
1962 struct Queue *queue = cls;
1963 ssize_t sent;
1964 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "In queue write\n");
1965 queue->write_task = NULL;
1966 if (0 != queue->cwrite_off)
1967 {
1968 sent = GNUNET_NETWORK_socket_send (queue->sock,
1969 queue->cwrite_buf,
1970 queue->cwrite_off);
1972 "Sent %lu bytes to TCP queue\n", sent);
1973 if ((-1 == sent) && (EAGAIN != errno) && (EINTR != errno))
1974 {
1977 return;
1978 }
1979 if (sent > 0)
1980 {
1981 size_t usent = (size_t) sent;
1982 queue->cwrite_off -= usent;
1983 memmove (queue->cwrite_buf,
1984 &queue->cwrite_buf[usent],
1985 queue->cwrite_off);
1986 queue->timeout =
1989 }
1990 }
1991 {
1992 /* can we encrypt more? (always encrypt full messages, needed
1993 such that #mq_cancel() can work!)
1994
1995 NOTE: this used to be gated on a `we_do_not_need_to_rekey' flag
1996 computed as `0 < rekey_left_bytes - (cwrite_off + pwrite_off +
1997 sizeof (struct TCPRekey))'. That subtraction is unsigned, so it
1998 wrapped to a huge value precisely when the rekey budget was about to
1999 run out -- inverting the test it was meant to express, and reporting
2000 "no rekey needed" even for a @e rekey_left_bytes of zero. The single
2001 value it did get right, exact equality, was worse still: it let the
2002 branch below call #inject_rekey() with a non-empty @e pwrite_buf,
2003 which that function asserts against, and if neither rekey trigger
2004 held it wedged this queue into a busy write loop that never drained
2005 @e pwrite_buf again -- a stall the peer sees as silence while the
2006 socket stays open and the communicator keeps reporting the queue up.
2007
2008 Encrypting a message first and rekeying immediately afterwards
2009 overshoots the byte budget by at most one message, which against the
2010 400 MB default is noise. */
2011 if ((queue->pwrite_off > 0) &&
2012 (queue->cwrite_off + queue->pwrite_off <= BUF_SIZE))
2013 {
2015 "Encrypting %lu bytes\n", queue->pwrite_off);
2016 GNUNET_assert (0 ==
2017 gcry_cipher_encrypt (queue->out_cipher,
2018 &queue->cwrite_buf[queue->cwrite_off],
2019 queue->pwrite_off,
2020 queue->pwrite_buf,
2021 queue->pwrite_off));
2022 if (queue->rekey_left_bytes > queue->pwrite_off)
2023 queue->rekey_left_bytes -= queue->pwrite_off;
2024 else
2025 queue->rekey_left_bytes = 0;
2026 queue->cwrite_off += queue->pwrite_off;
2027 queue->pwrite_off = 0;
2028 }
2029 /* Rekey once the byte budget is spent or the interval elapsed.
2030 #inject_rekey() requires an empty plaintext buffer (it asserts on it)
2031 and enough room in the ciphertext buffer; if either is missing we
2032 simply rekey on a later #queue_write(), which the write task above
2033 keeps arming for as long as anything is still buffered. */
2034 if (((0 == queue->rekey_left_bytes) ||
2036 queue->rekey_time).rel_value_us)) &&
2037 ((0 == queue->pwrite_off) &&
2038 (queue->cwrite_off + sizeof (struct TCPRekey) <= BUF_SIZE)))
2039 {
2041 }
2042 }
2043 if ((0 == queue->pwrite_off) && (! queue->finishing) &&
2044 (GNUNET_YES == queue->mq_awaits_continue))
2045 {
2046 queue->mq_awaits_continue = GNUNET_NO;
2048 }
2049 /* did we just finish writing 'finish'? */
2050 if ((0 == queue->cwrite_off) && (GNUNET_YES == queue->finishing))
2051 {
2053 "Finishing queue\n");
2055 return;
2056 }
2057 /* do we care to write more? */
2058 if ((0 < queue->cwrite_off) || (0 < queue->pwrite_off))
2059 queue->write_task =
2061 queue->sock,
2062 &queue_write,
2063 queue);
2064}
2065
2066
2074static size_t
2076{
2077 const struct GNUNET_MessageHeader *hdr;
2078 const struct TCPConfirmationAck *tca;
2079 const struct TCPBox *box;
2080 const struct TCPRekey *rekey;
2081 const struct TCPFinish *fin;
2082 struct TCPRekey rekeyz;
2083 struct TCPFinish finz;
2084 struct GNUNET_ShortHashCode tmac;
2085 uint16_t type;
2086 size_t size = 0;
2087 struct TcpHandshakeAckSignature thas;
2088 const struct GNUNET_PeerIdentity *my_identity;
2089 const struct GNUNET_CRYPTO_ChallengeNonceP challenge = queue->challenge;
2090
2092 "try handle plaintext!\n");
2093
2094 hdr = (const struct GNUNET_MessageHeader *) queue->pread_buf;
2095 if ((sizeof(*hdr) > queue->pread_off))
2096 {
2098 "Handling plaintext, not even a header!\n");
2099 return 0; /* not even a header */
2100 }
2101
2102 if ((GNUNET_YES != queue->initial_core_kx_done) && (queue->unverified_size >
2104 {
2106 "Already received data of size %lu bigger than KX size %lu!\n",
2107 queue->unverified_size,
2109 GNUNET_break_op (0);
2111 return 0;
2112 }
2113
2114 type = ntohs (hdr->type);
2115 switch (type)
2116 {
2118 tca = (const struct TCPConfirmationAck *) queue->pread_buf;
2120 "start processing ack\n");
2121 if (sizeof(*tca) > queue->pread_off)
2122 {
2124 "Handling plaintext size of tca greater than pread offset.\n")
2125 ;
2126 return 0;
2127 }
2128 if (ntohs (hdr->size) != sizeof(*tca))
2129 {
2131 "Handling plaintext size does not match message type.\n");
2132 GNUNET_break_op (0);
2134 return 0;
2135 }
2136
2139
2140 thas.purpose.purpose = htonl (
2142 thas.purpose.size = htonl (sizeof(thas));
2143 thas.sender = tca->sender;
2144 thas.receiver = *my_identity;
2145 thas.monotonic_time = tca->monotonic_time;
2146 thas.challenge = tca->challenge;
2147
2150 &thas,
2151 &tca->sender_sig,
2152 &tca->sender.public_key))
2153 {
2155 "Verification of signature failed!\n");
2156 GNUNET_break (0);
2158 return 0;
2159 }
2160 if (0 != GNUNET_memcmp (&tca->challenge, &challenge))
2161 {
2163 "Challenge in TCPConfirmationAck not correct!\n");
2164 GNUNET_break (0);
2166 return 0;
2167 }
2168
2169 queue->handshake_ack_monotime_get = GNUNET_PEERSTORE_iteration_start (
2170 peerstore,
2171 "transport_tcp_communicator",
2172 &queue->target,
2175 queue);
2176
2178 "Handling plaintext, ack processed!\n");
2179
2181 {
2182 send_challenge (queue->challenge_received, queue);
2183 queue->write_task =
2185 queue->sock,
2186 &queue_write,
2187 queue);
2188 }
2189 else if (GNUNET_TRANSPORT_CS_OUTBOUND == queue->cs)
2190 {
2192 queue->address->sa_family,
2193 &queue->target);
2194 }
2195
2200 queue->initial_core_kx_done = GNUNET_YES;
2201
2202 {
2203 char *foreign_addr;
2204
2205 switch (queue->address->sa_family)
2206 {
2207 case AF_INET:
2208 GNUNET_asprintf (&foreign_addr,
2209 "%s-%s",
2211 GNUNET_a2s (queue->address, queue->address_len));
2212 break;
2213
2214 case AF_INET6:
2215 GNUNET_asprintf (&foreign_addr,
2216 "%s-%s",
2218 GNUNET_a2s (queue->address, queue->address_len));
2219 break;
2220
2221 default:
2222 GNUNET_assert (0);
2223 }
2225 &queue->target,
2226 foreign_addr,
2227 UINT16_MAX, /* no MTU */
2229 0, /* Priority */
2230 queue->nt,
2231 queue->cs,
2232 queue->mq);
2233
2234 GNUNET_free (foreign_addr);
2235 }
2236
2237 size = ntohs (hdr->size);
2238 break;
2240 /* Special case: header size excludes box itself! */
2241 box = (const struct TCPBox *) queue->pread_buf;
2242 if (ntohs (hdr->size) + sizeof(struct TCPBox) > queue->pread_off)
2243 return 0;
2244 calculate_hmac (&queue->in_hmac, &box[1], ntohs (hdr->size), &tmac);
2245 if (0 != memcmp (&tmac, &box->hmac, sizeof(tmac)))
2246 {
2247 GNUNET_break_op (0);
2249 return 0;
2250 }
2251 pass_plaintext_to_core (queue, (const void *) &box[1], ntohs (hdr->size));
2252 size = ntohs (hdr->size) + sizeof(*box);
2254 "Handling plaintext, box processed!\n");
2256 "# bytes decrypted with BOX",
2257 size,
2258 GNUNET_NO);
2260 "# messages decrypted with BOX",
2261 1,
2262 GNUNET_NO);
2263 break;
2264
2266 rekey = (const struct TCPRekey *) queue->pread_buf;
2267 if (sizeof(*rekey) > queue->pread_off)
2268 return 0;
2269 if (ntohs (hdr->size) != sizeof(*rekey))
2270 {
2271 GNUNET_break_op (0);
2273 return 0;
2274 }
2275 rekeyz = *rekey;
2276 memset (&rekeyz.hmac, 0, sizeof(rekeyz.hmac));
2277 calculate_hmac (&queue->in_hmac, &rekeyz, sizeof(rekeyz), &tmac);
2278 if (0 != memcmp (&tmac, &rekey->hmac, sizeof(tmac)))
2279 {
2280 GNUNET_break_op (0);
2282 return 0;
2283 }
2284 do_rekey (queue, rekey);
2285 size = ntohs (hdr->size);
2287 "Handling plaintext, rekey processed!\n");
2289 "# rekeying successful",
2290 1,
2291 GNUNET_NO);
2292 break;
2293
2295 fin = (const struct TCPFinish *) queue->pread_buf;
2296 if (sizeof(*fin) > queue->pread_off)
2297 return 0;
2298 if (ntohs (hdr->size) != sizeof(*fin))
2299 {
2300 GNUNET_break_op (0);
2302 return 0;
2303 }
2304 finz = *fin;
2305 memset (&finz.hmac, 0, sizeof(finz.hmac));
2306 calculate_hmac (&queue->in_hmac, &finz, sizeof(finz), &tmac);
2307 if (0 != memcmp (&tmac, &fin->hmac, sizeof(tmac)))
2308 {
2309 GNUNET_break_op (0);
2311 return 0;
2312 }
2313 /* handle FINISH by destroying queue */
2315 "Handling plaintext, finish processed!\n");
2317 /* NOTE: must return here rather than `break'. #queue_destroy() releases
2318 @a queue outright once its backpressure has drained, so neither the
2319 @e unverified_size accounting below nor #queue_read()'s loop may look
2320 at it again. Falling through also hit `GNUNET_assert (0 != size)'
2321 with @a size still zero -- receiving a perfectly ordinary FINISH thus
2322 aborted the communicator, taking every other queue down with it. */
2323 return TCP_QUEUE_GONE;
2324
2325 default:
2327 "Handling plaintext, nothing processed!\n");
2328 GNUNET_break_op (0);
2330 return 0;
2331 }
2332 GNUNET_assert (0 != size);
2333 if (-1 != queue->unverified_size)
2334 queue->unverified_size += size;
2335 return size;
2336}
2337
2338
2344static void
2345queue_read (void *cls)
2346{
2347 struct Queue *queue = cls;
2348 struct GNUNET_TIME_Relative left;
2349 ssize_t rcvd;
2350
2351 queue->read_task = NULL;
2352 rcvd = GNUNET_NETWORK_socket_recv (queue->sock,
2353 &queue->cread_buf[queue->cread_off],
2354 BUF_SIZE - queue->cread_off);
2356 "Received %zd bytes from TCP queue\n", rcvd);
2357 if (-1 == rcvd)
2358 {
2359 if ((EAGAIN != errno) && (EINTR != errno))
2360 {
2363 return;
2364 }
2365 /* try again */
2366 left = GNUNET_TIME_absolute_get_remaining (queue->timeout);
2367 if (0 != left.rel_value_us)
2368 {
2369 queue->read_task =
2371 return;
2372 }
2374 "Queue %p was idle for %s, disconnecting\n",
2375 queue,
2378 GNUNET_YES));
2380 return;
2381 }
2382 if (0 == rcvd)
2383 {
2384 /* Orderly shutdown of connection */
2386 "Socket for queue %p seems to have been closed\n", queue);
2388 return;
2389 }
2390 queue->timeout =
2392 queue->cread_off += rcvd;
2393 while ((queue->pread_off < sizeof(queue->pread_buf)) &&
2394 (queue->cread_off > 0))
2395 {
2396 size_t max = GNUNET_MIN (sizeof(queue->pread_buf) - queue->pread_off,
2397 queue->cread_off);
2398 size_t done;
2399 size_t total;
2400 size_t old_pread_off = queue->pread_off;
2401
2402 GNUNET_assert (0 ==
2403 gcry_cipher_decrypt (queue->in_cipher,
2404 &queue->pread_buf[queue->pread_off],
2405 max,
2406 queue->cread_buf,
2407 max));
2408 queue->pread_off += max;
2409 total = 0;
2410 while (0 != (done = try_handle_plaintext (queue)))
2411 {
2412 if (TCP_QUEUE_GONE == done)
2413 return; /* @a queue was destroyed under us, do not touch it */
2414 /* 'done' bytes of plaintext were used, shift buffer */
2415 GNUNET_assert (done <= queue->pread_off);
2416 /* NOTE: this memmove() could possibly sometimes be
2417 avoided if we pass 'total' into try_handle_plaintext()
2418 and use it at an offset into the buffer there! */
2419 memmove (queue->pread_buf,
2420 &queue->pread_buf[done],
2421 queue->pread_off - done);
2422 queue->pread_off -= done;
2423 total += done;
2424 /* The last plaintext was a rekey, abort for now */
2425 if (GNUNET_YES == queue->rekeyed)
2426 break;
2427 }
2428 /* when we encounter a rekey message, the decryption above uses the
2429 wrong key for everything after the rekey; in that case, we have
2430 to re-do the decryption at 'total' instead of at 'max'.
2431 However, we have to take into account that the plaintext buffer may have
2432 already contained data and not jumped too far ahead in the ciphertext.
2433 If there is no rekey and the last message is incomplete (max > total),
2434 it is safe to keep the decryption so we shift by 'max' */
2435 if (GNUNET_YES == queue->rekeyed)
2436 {
2437 max = total - old_pread_off;
2438 queue->rekeyed = GNUNET_NO;
2439 queue->pread_off = 0;
2440 }
2441 memmove (queue->cread_buf, &queue->cread_buf[max], queue->cread_off - max);
2442 queue->cread_off -= max;
2443 }
2444 if (BUF_SIZE == queue->cread_off)
2445 return; /* buffer full, suspend reading */
2446 left = GNUNET_TIME_absolute_get_remaining (queue->timeout);
2447 if (0 != left.rel_value_us)
2448 {
2449 if (max_queue_length > queue->backpressure)
2450 {
2451 /* continue reading */
2452 queue->read_task =
2454 }
2455 return;
2456 }
2458 "Queue %p was idle for %s, disconnecting\n",
2459 queue,
2462 GNUNET_YES));
2464}
2465
2466
2474static struct sockaddr *
2476 struct sockaddr_in6 v6,
2477 unsigned int port)
2478{
2479 struct sockaddr *in;
2480
2481 v6.sin6_family = AF_INET6;
2482 v6.sin6_port = htons ((uint16_t) port);
2483#if HAVE_SOCKADDR_IN_SIN_LEN
2484 v6.sin6_len = sizeof(struct sockaddr_in6);
2485#endif
2486 v6.sin6_flowinfo = 0;
2487 v6.sin6_scope_id = 0;
2488 in = GNUNET_memdup (&v6, sizeof(v6));
2489 *sock_len = sizeof(struct sockaddr_in6);
2490
2491 return in;
2492}
2493
2494
2502static struct sockaddr *
2504 struct sockaddr_in v4,
2505 unsigned int port)
2506{
2507 struct sockaddr *in;
2508
2509 v4.sin_family = AF_INET;
2510 v4.sin_port = htons ((uint16_t) port);
2511#if HAVE_SOCKADDR_IN_SIN_LEN
2512 v4.sin_len = sizeof(struct sockaddr_in);
2513#endif
2514 in = GNUNET_memdup (&v4, sizeof(v4));
2515 *sock_len = sizeof(struct sockaddr_in);
2516 return in;
2517}
2518
2519
2526static struct PortOnlyIpv4Ipv6 *
2527tcp_address_to_sockaddr_port_only (const char *bindto, unsigned int *port)
2528{
2529 struct PortOnlyIpv4Ipv6 *po;
2530 struct sockaddr_in *i4;
2531 struct sockaddr_in6 *i6;
2532 socklen_t sock_len_ipv4;
2533 socklen_t sock_len_ipv6;
2534
2535 /* interpreting value as just a PORT number */
2536 if (*port > UINT16_MAX)
2537 {
2539 "BINDTO specification `%s' invalid: value too large for port\n",
2540 bindto);
2541 return NULL;
2542 }
2543
2544 po = GNUNET_new (struct PortOnlyIpv4Ipv6);
2545
2546 if (GNUNET_YES == disable_v6)
2547 {
2548 i4 = GNUNET_malloc (sizeof(struct sockaddr_in));
2549 po->addr_ipv4 = tcp_address_to_sockaddr_numeric_v4 (&sock_len_ipv4, *i4,
2550 *port);
2551 po->addr_len_ipv4 = sock_len_ipv4;
2552 }
2553 else
2554 {
2555
2556 i4 = GNUNET_malloc (sizeof(struct sockaddr_in));
2557 po->addr_ipv4 = tcp_address_to_sockaddr_numeric_v4 (&sock_len_ipv4, *i4,
2558 *port);
2559 po->addr_len_ipv4 = sock_len_ipv4;
2560
2561 i6 = GNUNET_malloc (sizeof(struct sockaddr_in6));
2562 po->addr_ipv6 = tcp_address_to_sockaddr_numeric_v6 (&sock_len_ipv6, *i6,
2563 *port);
2564
2565 po->addr_len_ipv6 = sock_len_ipv6;
2566
2567 GNUNET_free (i6);
2568 }
2569
2570 GNUNET_free (i4);
2571
2572 return po;
2573}
2574
2575
2582static char *
2583extract_address (const char *bindto)
2584{
2585 char *addr;
2586 char *start;
2587 char *token;
2588 char *cp;
2589 char *rest = NULL;
2590
2592 "extract address with bindto %s\n",
2593 bindto);
2594
2595 if (NULL == bindto)
2597 "bindto is NULL\n");
2598
2599 cp = GNUNET_strdup (bindto);
2600
2602 "extract address 2\n");
2603
2604 start = cp;
2605 if (('[' == *cp) && (']' == cp[strlen (cp) - 1]))
2606 {
2607 start++; /* skip over '['*/
2608 cp[strlen (cp) - 1] = '\0'; /* eat ']'*/
2609 addr = GNUNET_strdup (start);
2610 }
2611 else
2612 {
2613 token = strtok_r (cp, "]", &rest);
2614 if (strlen (bindto) == strlen (token))
2615 {
2616 token = strtok_r (cp, ":", &rest);
2617 addr = GNUNET_strdup (token);
2618 }
2619 else
2620 {
2621 token++;
2622 addr = GNUNET_strdup (token);
2623 }
2624 }
2625
2627 "tcp address: %s\n",
2628 addr);
2629 GNUNET_free (cp);
2630 return addr;
2631}
2632
2633
2640static unsigned int
2641extract_port (const char *addr_and_port)
2642{
2643 unsigned int port;
2644 char dummy[2];
2645 char *token;
2646 char *addr;
2647 char *colon;
2648 char *cp;
2649 char *rest = NULL;
2650
2651 if (NULL != addr_and_port)
2652 {
2653 cp = GNUNET_strdup (addr_and_port);
2654 token = strtok_r (cp, "]", &rest);
2655 if (strlen (addr_and_port) == strlen (token))
2656 {
2657 colon = strrchr (cp, ':');
2658 if (NULL == colon)
2659 {
2660 GNUNET_free (cp);
2661 return 0;
2662 }
2663 addr = colon;
2664 addr++;
2665 }
2666 else
2667 {
2668 token = strtok_r (NULL, "]", &rest);
2669 if (NULL == token)
2670 {
2671 GNUNET_free (cp);
2672 return 0;
2673 }
2674 else
2675 {
2676 addr = token;
2677 addr++;
2678 }
2679 }
2680
2681
2682 if (1 == sscanf (addr, "%u%1s", &port, dummy))
2683 {
2684 /* interpreting value as just a PORT number */
2685 if (port > UINT16_MAX)
2686 {
2688 "Port `%u' invalid: value too large for port\n",
2689 port);
2690 GNUNET_free (cp);
2691 return 0;
2692 }
2693 }
2694 else
2695 {
2697 "BINDTO specification invalid: last ':' not followed by number\n");
2698 GNUNET_free (cp);
2699 return 0;
2700 }
2701 GNUNET_free (cp);
2702 }
2703 else
2704 {
2706 "return 0\n");
2707 /* interpret missing port as 0, aka pick any free one */
2708 port = 0;
2709 }
2710
2711 return port;
2712}
2713
2714
2722static struct sockaddr *
2723tcp_address_to_sockaddr (const char *bindto, socklen_t *sock_len)
2724{
2725 struct sockaddr *in;
2726 unsigned int port;
2727 struct sockaddr_in v4;
2728 struct sockaddr_in6 v6;
2729 char *start;
2730
2731 memset (&v4, 0, sizeof(v4));
2732 start = extract_address (bindto);
2733 GNUNET_assert (NULL != start);
2735 "start %s\n",
2736 start);
2737
2739 "!bindto %s\n",
2740 bindto);
2741
2742
2743 if (1 == inet_pton (AF_INET, start, &v4.sin_addr))
2744 {
2745 port = extract_port (bindto);
2746
2748 "port %u\n",
2749 port);
2750
2751 in = tcp_address_to_sockaddr_numeric_v4 (sock_len, v4, port);
2752 }
2753 else if (1 == inet_pton (AF_INET6, start, &v6.sin6_addr))
2754 {
2755 port = extract_port (bindto);
2756 in = tcp_address_to_sockaddr_numeric_v6 (sock_len, v6, port);
2757 }
2758 else
2759 {
2760 GNUNET_assert (0);
2761 }
2762
2764 return in;
2765}
2766
2767
2776static void
2778 const struct GNUNET_MessageHeader *msg,
2779 void *impl_state)
2780{
2781 struct Queue *queue = impl_state;
2782 uint16_t msize = ntohs (msg->size);
2783 struct TCPBox box;
2785 "In MQ send. Queue finishing: %s; write task running: %s\n",
2786 (GNUNET_YES == queue->finishing) ? "yes" : "no",
2787 (NULL == queue->write_task) ? "yes" : "no");
2788 GNUNET_assert (mq == queue->mq);
2789 queue->mq_awaits_continue = GNUNET_YES;
2790 if (GNUNET_YES == queue->finishing)
2791 return; /* this queue is dying, drop msg */
2792 GNUNET_assert (0 == queue->pwrite_off);
2794 box.header.size = htons (msize);
2795 calculate_hmac (&queue->out_hmac, msg, msize, &box.hmac);
2796 memcpy (&queue->pwrite_buf[queue->pwrite_off], &box, sizeof(box));
2797 queue->pwrite_off += sizeof(box);
2798 memcpy (&queue->pwrite_buf[queue->pwrite_off], msg, msize);
2799 queue->pwrite_off += msize;
2801 "%lu bytes of plaintext to send\n", queue->pwrite_off);
2802 GNUNET_assert (NULL != queue->sock);
2803 if (NULL == queue->write_task)
2804 queue->write_task =
2806 queue->sock,
2807 &queue_write,
2808 queue);
2809}
2810
2811
2820static void
2821mq_destroy (struct GNUNET_MQ_Handle *mq, void *impl_state)
2822{
2823 struct Queue *queue = impl_state;
2824
2825 if (mq == queue->mq)
2826 {
2827 queue->mq = NULL;
2829 }
2830}
2831
2832
2839static void
2840mq_cancel (struct GNUNET_MQ_Handle *mq, void *impl_state)
2841{
2842 struct Queue *queue = impl_state;
2843
2844 GNUNET_assert (0 != queue->pwrite_off);
2845 queue->pwrite_off = 0;
2846}
2847
2848
2858static void
2859mq_error (void *cls, enum GNUNET_MQ_Error error)
2860{
2861 struct Queue *queue = cls;
2862
2864 "MQ error in queue to %s: %d\n",
2865 GNUNET_i2s (&queue->target),
2866 (int) error);
2868}
2869
2870
2878static void
2880{
2881 queue->nt =
2882 GNUNET_NT_scanner_get_type (is, queue->address, queue->address_len);
2884 queue_map,
2885 &queue->key,
2886 queue,
2889 "# queues active",
2891 GNUNET_NO);
2892 queue->timeout =
2895 &mq_destroy,
2896 &mq_cancel,
2897 queue,
2898 NULL,
2899 &mq_error,
2900 queue);
2901}
2902
2903
2914static void
2916 const struct GNUNET_CRYPTO_HpkeEncapsulation *c)
2917{
2918 const struct GNUNET_PeerIdentity *my_identity;
2920 struct TcpHandshakeSignature ths;
2921 struct TCPConfirmation tc;
2922
2926
2927 memcpy (queue->cwrite_buf, c, sizeof(*c));
2928 queue->cwrite_off = sizeof(*c);
2929 /* compute 'tc' and append in encrypted format to cwrite_buf */
2930 tc.sender = *my_identity;
2931 tc.monotonic_time =
2933 GNUNET_CRYPTO_random_block (&tc.challenge,
2934 sizeof(tc.challenge));
2935 ths.purpose.purpose = htonl (
2937 ths.purpose.size = htonl (sizeof(ths));
2938 ths.sender = *my_identity;
2939 ths.receiver = queue->target;
2940 ths.ephemeral = *c;
2941 ths.monotonic_time = tc.monotonic_time;
2942 ths.challenge = tc.challenge;
2944 &ths,
2945 &tc.sender_sig);
2946 GNUNET_assert (0 ==
2947 gcry_cipher_encrypt (queue->out_cipher,
2948 &queue->cwrite_buf[queue->cwrite_off],
2949 sizeof(tc),
2950 &tc,
2951 sizeof(tc)));
2952 queue->challenge = tc.challenge;
2953 queue->cwrite_off += sizeof(tc);
2954
2956 "handshake written\n");
2957}
2958
2959
2967static void
2969{
2971 struct GNUNET_ShortHashCode k;
2972
2974 &c, &k);
2975 setup_out_cipher (queue, &k);
2976 transmit_kx (queue, &c);
2977}
2978
2979
2985static void
2986handshake_monotime_store_cb (void *cls, int success)
2987{
2988 struct Queue *queue = cls;
2989 if (GNUNET_OK != success)
2990 {
2992 "Failed to store handshake monotonic time in PEERSTORE!\n");
2993 }
2994 queue->handshake_monotime_sc = NULL;
2995 GNUNET_PEERSTORE_iteration_next (queue->handshake_ack_monotime_get, 1);
2996}
2997
2998
3006static void
3008 const struct GNUNET_PEERSTORE_Record *record,
3009 const char *emsg)
3010{
3011 struct Queue *queue = cls;
3012 struct GNUNET_TIME_AbsoluteNBO *mtbe;
3013 struct GNUNET_TIME_Absolute mt;
3014 const struct GNUNET_PeerIdentity *pid;
3015 struct GNUNET_TIME_AbsoluteNBO *handshake_monotonic_time;
3016
3017 (void) emsg;
3018
3019 handshake_monotonic_time = &queue->handshake_monotonic_time;
3020 pid = &queue->target;
3022 "tcp handshake with us %s\n",
3024 if (NULL == record)
3025 {
3026 queue->handshake_monotime_get = NULL;
3027 return;
3028 }
3030 "tcp handshake from peer %s\n",
3031 GNUNET_i2s (pid));
3032 if (sizeof(*mtbe) != record->value_size)
3033 {
3034 GNUNET_PEERSTORE_iteration_next (queue->handshake_ack_monotime_get, 1);
3035 GNUNET_break (0);
3036 return;
3037 }
3038 mtbe = record->value;
3039 mt = GNUNET_TIME_absolute_ntoh (*mtbe);
3041 queue->handshake_monotonic_time).abs_value_us)
3042 {
3044 "Queue from %s dropped, handshake monotime in the past\n",
3045 GNUNET_i2s (&queue->target));
3046 GNUNET_break (0);
3047 GNUNET_PEERSTORE_iteration_stop (queue->handshake_ack_monotime_get);
3048 queue->handshake_ack_monotime_get = NULL;
3050 return;
3051 }
3052 queue->handshake_monotime_sc = GNUNET_PEERSTORE_store (peerstore,
3053 "transport_tcp_communicator",
3054 pid,
3056 handshake_monotonic_time,
3057 sizeof(*
3058 handshake_monotonic_time),
3061 &
3063 queue);
3064}
3065
3066
3078static int
3080 struct TCPConfirmation *tc,
3081 char *ibuf)
3082{
3083 const struct GNUNET_PeerIdentity *my_identity;
3084 struct TcpHandshakeSignature ths;
3086
3089
3091 0 ==
3092 gcry_cipher_decrypt (queue->in_cipher,
3093 tc,
3094 sizeof(*tc),
3095 &ibuf[sizeof(struct GNUNET_CRYPTO_EcdhePublicKey)],
3096 sizeof(*tc)));
3097 ths.purpose.purpose = htonl (
3099 ths.purpose.size = htonl (sizeof(ths));
3100 ths.sender = tc->sender;
3101 ths.receiver = *my_identity;
3102 memcpy (&ths.ephemeral, ibuf, sizeof(struct GNUNET_CRYPTO_EcdhePublicKey));
3103 ths.monotonic_time = tc->monotonic_time;
3104 ths.challenge = tc->challenge;
3107 &ths,
3108 &tc->sender_sig,
3109 &tc->sender.public_key);
3110 if (GNUNET_YES == ret)
3111 queue->handshake_monotime_get =
3113 "transport_tcp_communicator",
3114 &queue->target,
3117 queue);
3118 return ret;
3119}
3120
3121
3129static void
3130queue_read_kx (void *cls)
3131{
3132 struct Queue *queue = cls;
3133 ssize_t rcvd;
3134 struct GNUNET_TIME_Relative left;
3135 struct TCPConfirmation tc;
3136
3137 queue->read_task = NULL;
3138 left = GNUNET_TIME_absolute_get_remaining (queue->timeout);
3139 if (0 == left.rel_value_us)
3140 {
3142 return;
3143 }
3144 rcvd = GNUNET_NETWORK_socket_recv (queue->sock,
3145 &queue->cread_buf[queue->cread_off],
3146 BUF_SIZE - queue->cread_off);
3148 "Received %lu bytes to write in buffer of size %lu for KX from queue %p (expires in %"
3149 PRIu64 ")\n",
3150 rcvd, BUF_SIZE - queue->cread_off, queue, left.rel_value_us);
3151 if (-1 == rcvd)
3152 {
3153 if ((EAGAIN != errno) && (EINTR != errno))
3154 {
3157 return;
3158 }
3159 queue->read_task =
3161 return;
3162 }
3163 if (0 == rcvd)
3164 {
3165 /* Orderly shutdown of connection */
3167 "Socket for queue %p seems to have been closed\n", queue);
3169 return;
3170 }
3171 queue->cread_off += rcvd;
3172 if (queue->cread_off < INITIAL_KX_SIZE)
3173 {
3174 /* read more */
3176 "%lu/%lu bytes of KX read. Rescheduling...\n",
3177 queue->cread_off, INITIAL_KX_SIZE);
3178 queue->read_task =
3180 return;
3181 }
3182 /* we got all the data, let's find out who we are talking to! */
3184 (const struct GNUNET_CRYPTO_HpkeEncapsulation*)
3185 queue->cread_buf,
3186 queue);
3187 if (GNUNET_OK != decrypt_and_check_tc (queue, &tc, queue->cread_buf))
3188 {
3190 "Invalid TCP KX received from %s\n",
3191 GNUNET_a2s (queue->address, queue->address_len));
3193 return;
3194 }
3195 if (0 !=
3196 memcmp (&tc.sender, &queue->target, sizeof(struct GNUNET_PeerIdentity)))
3197 {
3199 "Invalid sender in TCP KX received from %s\n",
3200 GNUNET_a2s (queue->address, queue->address_len));
3202 return;
3203 }
3204 send_challenge (tc.challenge, queue);
3205 queue->write_task =
3207 queue->sock,
3208 &queue_write,
3209 queue);
3210
3211 /* update queue timeout */
3212 queue->timeout =
3214 /* prepare to continue with regular read task immediately */
3215 memmove (queue->cread_buf,
3216 &queue->cread_buf[INITIAL_KX_SIZE],
3217 queue->cread_off - (INITIAL_KX_SIZE));
3219 "cread_off is %lu bytes before adjusting\n",
3220 queue->cread_off);
3221 queue->cread_off -= INITIAL_KX_SIZE;
3223 "cread_off set to %lu bytes\n",
3224 queue->cread_off);
3226}
3227
3228
3235static void
3236proto_read_kx (void *cls)
3237{
3238 struct ProtoQueue *pq = cls;
3239 ssize_t rcvd;
3240 struct GNUNET_TIME_Relative left;
3241 struct Queue *queue;
3242 struct TCPConfirmation tc;
3244
3245 pq->read_task = NULL;
3247 if (0 == left.rel_value_us)
3248 {
3249 free_proto_queue (pq);
3250 return;
3251 }
3252 rcvd = GNUNET_NETWORK_socket_recv (pq->sock,
3253 &pq->ibuf[pq->ibuf_off],
3254 sizeof(pq->ibuf) - pq->ibuf_off);
3256 "Proto received %lu bytes for KX\n", rcvd);
3257 if (-1 == rcvd)
3258 {
3259 if ((EAGAIN != errno) && (EINTR != errno))
3260 {
3262 free_proto_queue (pq);
3263 return;
3264 }
3265 /* try again */
3266 pq->read_task =
3268 return;
3269 }
3270 if (0 == rcvd)
3271 {
3272 /* Orderly shutdown of connection */
3274 "Socket for proto queue %p seems to have been closed\n", pq);
3275 free_proto_queue (pq);
3276 return;
3277 }
3278 pq->ibuf_off += rcvd;
3279 if (sizeof (struct TCPNATProbeMessage) == pq->ibuf_off)
3280 {
3281 struct TCPNATProbeMessage *pm = (struct TCPNATProbeMessage *) pq->ibuf;
3282
3284 &pm->clientIdentity);
3285
3286 queue = GNUNET_new (struct Queue);
3287 queue->target = pm->clientIdentity;
3288 eddsa_pub_to_hpke_key (&queue->target.public_key,
3289 &queue->target_hpke_key);
3292 }
3293 else if (pq->ibuf_off < sizeof(pq->ibuf))
3294 {
3295 /* read more */
3296 pq->read_task =
3298 return;
3299 }
3300 else
3301 {
3302 /* we got all the data, let's find out who we are talking to! */
3303 queue = GNUNET_new (struct Queue);
3305 (const struct GNUNET_CRYPTO_HpkeEncapsulation *) pq->
3306 ibuf,
3307 queue);
3308 if (GNUNET_OK != decrypt_and_check_tc (queue, &tc, pq->ibuf))
3309 {
3311 "Invalid TCP KX received from %s\n",
3312 GNUNET_a2s (pq->address, pq->address_len));
3313 gcry_cipher_close (queue->in_cipher);
3315 free_proto_queue (pq);
3316 return;
3317 }
3318 queue->target = tc.sender;
3319 eddsa_pub_to_hpke_key (&queue->target.public_key,
3320 &queue->target_hpke_key);
3323 }
3324 queue->address = pq->address; /* steals reference */
3325 queue->address_len = pq->address_len;
3326 queue->listen_sock = pq->listen_sock;
3327 queue->sock = pq->sock;
3328
3330 "created queue with target %s\n",
3331 GNUNET_i2s (&queue->target));
3332
3334 "start kx proto\n");
3335
3337 boot_queue (queue);
3338 queue->read_task =
3340 queue->sock,
3341 read_task,
3342 queue);
3343 queue->write_task =
3345 queue->sock,
3346 &queue_write,
3347 queue);
3348 // TODO To early! Move it somewhere else.
3349 // send_challenge (tc.challenge, queue);
3350 queue->challenge_received = tc.challenge;
3351
3353 GNUNET_free (pq);
3354}
3355
3356
3357static struct ProtoQueue *
3359 struct sockaddr *in,
3360 socklen_t addrlen)
3361{
3362 struct ProtoQueue *pq = GNUNET_new (struct ProtoQueue);
3363
3364 if (NULL == sock)
3365 {
3366 // sock = GNUNET_CONNECTION_create_from_sockaddr (AF_INET, addr, addrlen);
3367 sock = GNUNET_NETWORK_socket_create (in->sa_family, SOCK_STREAM, 0);
3368 if (NULL == sock)
3369 {
3371 "socket(%d) failed: %s",
3372 in->sa_family,
3373 strerror (errno));
3374 GNUNET_free (in);
3375 GNUNET_free (pq);
3376 return NULL;
3377 }
3378 if ((GNUNET_OK != GNUNET_NETWORK_socket_connect (sock, in, addrlen)) &&
3379 (errno != EINPROGRESS))
3380 {
3382 "connect to `%s' failed: %s",
3383 GNUNET_a2s (in, addrlen),
3384 strerror (errno));
3386 GNUNET_free (in);
3387 GNUNET_free (pq);
3388 return NULL;
3389 }
3390 }
3391 pq->address_len = addrlen;
3392 pq->address = in;
3394 pq->sock = sock;
3396 pq->sock,
3398 pq);
3400
3401 return pq;
3402}
3403
3404
3412static void
3413listen_cb (void *cls)
3414{
3415 struct sockaddr_storage in;
3416 socklen_t addrlen;
3417 struct GNUNET_NETWORK_Handle *sock;
3418 struct ListenTask *lt;
3419 struct sockaddr *in_addr;
3420
3422 "listen_cb\n");
3423
3424 lt = cls;
3425
3426 lt->listen_task = NULL;
3427 GNUNET_assert (NULL != lt->listen_sock);
3428 addrlen = sizeof(in);
3429 memset (&in, 0, sizeof(in));
3431 (struct sockaddr*) &in,
3432 &addrlen);
3433 if ((NULL == sock) && ((EMFILE == errno) || (ENFILE == errno)))
3434 return; /* system limit reached, wait until connection goes down */
3436 lt->listen_sock,
3437 &listen_cb,
3438 lt);
3439 if ((NULL == sock) && ((EAGAIN == errno) || (ENOBUFS == errno)))
3440 return;
3441 if (NULL == sock)
3442 {
3444 return;
3445 }
3446 in_addr = GNUNET_memdup (&in, addrlen);
3447 create_proto_queue (sock, in_addr, addrlen);
3448}
3449
3450
3451static void
3453 const struct sockaddr *addr,
3454 socklen_t addrlen)
3455{
3456 const struct GNUNET_PeerIdentity *my_identity;
3457 struct TCPNATProbeMessage pm;
3458 struct ProtoQueue *pq;
3459 struct sockaddr *in_addr;
3460 (void) cls;
3461
3464
3466 "addr->sa_family %d\n",
3467 addr->sa_family);
3469 "Try to connect back\n");
3470 in_addr = GNUNET_memdup (addr, addrlen);
3472 "in_addr->sa_family %d\n",
3473 in_addr->sa_family);
3474 pq = create_proto_queue (NULL, in_addr, addrlen);
3475 if (NULL != pq)
3476 {
3477 pm.header.size = htons (sizeof(struct TCPNATProbeMessage));
3480 memcpy (pq->write_buf, &pm, sizeof(struct TCPNATProbeMessage));
3481 pq->write_off = sizeof(struct TCPNATProbeMessage);
3483 pq->sock,
3485 pq);
3486 }
3487 else
3488 {
3490 "Couldn't create ProtoQueue for sending TCPNATProbeMessage\n");
3491 }
3492}
3493
3494
3495static void
3497{
3498 struct PendingReversal *pending_reversal = cls;
3499 struct GNUNET_HashCode key;
3500
3501 pending_reversal->timeout_task = NULL;
3502 pending_reversal_key (pending_reversal->in,
3503 &pending_reversal->target,
3504 &key);
3506 &key,
3507 pending_reversal))
3509 "No pending reversal found for address %s\n",
3510 GNUNET_a2s (pending_reversal->in,
3511 sizeof (struct sockaddr)));
3512 GNUNET_free (pending_reversal->in);
3513 GNUNET_free (pending_reversal);
3514}
3515
3516
3535static int
3536mq_init (void *cls, const struct GNUNET_PeerIdentity *peer, const char *address)
3537{
3538 struct sockaddr *in;
3539 socklen_t in_len = 0;
3540 const char *path;
3541 struct sockaddr_in *v4;
3542 struct sockaddr_in6 *v6;
3543 unsigned int is_natd = GNUNET_NO;
3544 struct GNUNET_HashCode key;
3545 struct GNUNET_HashCode queue_map_key;
3546 struct GNUNET_HashContext *hsh;
3547 struct Queue *queue;
3548
3550 "Connecting to %s at %s\n",
3551 GNUNET_i2s (peer),
3552 address);
3553 if (0 != strncmp (address,
3555 strlen (COMMUNICATOR_ADDRESS_PREFIX "-")))
3556 {
3557 GNUNET_break_op (0);
3558 return GNUNET_SYSERR;
3559 }
3560 path = &address[strlen (COMMUNICATOR_ADDRESS_PREFIX "-")];
3561 in = tcp_address_to_sockaddr (path, &in_len);
3562
3563 if (NULL == in)
3564 {
3566 "Failed to setup TCP socket address\n");
3567 return GNUNET_SYSERR;
3568 }
3569
3571 "in %s\n",
3572 GNUNET_a2s (in, in_len));
3573
3574 if (AF_INET6 == in->sa_family)
3575 {
3576 const struct sockaddr_in6 *v6 = (const struct sockaddr_in6 *) in;
3577
3578 /* A link-local address is only meaningful together with the interface
3579 it was learned on, and that scope does not survive being carried to
3580 another host in a HELLO. connect() to one with a zero scope id fails
3581 with EINVAL every single time, so trying is pure noise: peers gossip
3582 these by the dozen and each attempt logged a WARNING. */
3583 if (IN6_IS_ADDR_LINKLOCAL (&v6->sin6_addr) && (0 == v6->sin6_scope_id))
3584 {
3586 "Skipping unusable link-local address `%s' for `%s'\n",
3587 address,
3588 GNUNET_i2s (peer));
3589 GNUNET_free (in);
3590 return GNUNET_SYSERR;
3591 }
3592 }
3593
3596 GNUNET_CRYPTO_hash_context_read (hsh, peer, sizeof (*peer));
3597 GNUNET_CRYPTO_hash_context_finish (hsh, &queue_map_key);
3599
3600 if (NULL != queue)
3601 {
3603 "Queue for %s already exists or is in construction\n", address);
3604 GNUNET_free (in);
3605 return GNUNET_NO;
3606 }
3607 switch (in->sa_family)
3608 {
3609 case AF_INET:
3610 v4 = (struct sockaddr_in *) in;
3611 if (0 == v4->sin_port)
3612 {
3613 is_natd = GNUNET_YES;
3614 pending_reversal_key (in, peer, &key);
3617 &key))
3618 {
3620 "There is already a request reversal for `%s' at `%s'\n",
3621 GNUNET_i2s (peer),
3622 address);
3623 GNUNET_free (in);
3624 return GNUNET_SYSERR;
3625 }
3626 }
3627 break;
3628
3629 case AF_INET6:
3630 if (GNUNET_YES == disable_v6)
3631 {
3633 "IPv6 disabled, skipping %s\n", address);
3634 GNUNET_free (in);
3635 return GNUNET_SYSERR;
3636 }
3637 v6 = (struct sockaddr_in6 *) in;
3638 if (0 == v6->sin6_port)
3639 {
3641 "Request reversal for `%s' at `%s' not possible for an IPv6 address\n",
3642 GNUNET_i2s (peer),
3643 address);
3644 GNUNET_free (in);
3645 return GNUNET_SYSERR;
3646 }
3647 break;
3648
3649 default:
3650 GNUNET_assert (0);
3651 }
3652
3653 if (GNUNET_YES == is_natd)
3654 {
3655 struct sockaddr_in local_sa;
3656 struct PendingReversal *pending_reversal;
3657
3658 memset (&local_sa, 0, sizeof(local_sa));
3659 local_sa.sin_family = AF_INET;
3660 local_sa.sin_port = htons (bind_port);
3661 /* We leave sin_address at 0, let the kernel figure it out,
3662 even if our bind() is more specific. (May want to reconsider
3663 later.) */
3664 if (GNUNET_OK != GNUNET_NAT_request_reversal (nat, &local_sa, v4))
3665 {
3667 "request reversal for `%s' at `%s' failed\n",
3668 GNUNET_i2s (peer),
3669 address);
3670 GNUNET_free (in);
3671 return GNUNET_SYSERR;
3672 }
3673 pending_reversal = GNUNET_new (struct PendingReversal);
3674 pending_reversal->in = in;
3677 &key,
3678 pending_reversal,
3680 pending_reversal->target = *peer;
3681 pending_reversal->timeout_task = GNUNET_SCHEDULER_add_delayed (
3684 pending_reversal);
3686 "Created NAT WAIT connection to `%s' at `%s'\n",
3687 GNUNET_i2s (peer),
3688 GNUNET_a2s (in, sizeof (struct sockaddr)));
3689 }
3690 else
3691 {
3692 struct GNUNET_NETWORK_Handle *sock;
3693
3694 sock = GNUNET_NETWORK_socket_create (in->sa_family, SOCK_STREAM,
3695 IPPROTO_TCP);
3696 if (NULL == sock)
3697 {
3699 "socket(%d) failed: %s",
3700 in->sa_family,
3701 strerror (errno));
3702 GNUNET_free (in);
3703 return GNUNET_SYSERR;
3704 }
3705 if ((GNUNET_OK != GNUNET_NETWORK_socket_connect (sock, in, in_len)) &&
3706 (errno != EINPROGRESS))
3707 {
3709 "connect to `%s' failed: %s",
3710 address,
3711 strerror (errno));
3713 GNUNET_free (in);
3714 return GNUNET_SYSERR;
3715 }
3716
3717 queue = GNUNET_new (struct Queue);
3718 queue->target = *peer;
3719 eddsa_pub_to_hpke_key (&queue->target.public_key, &queue->target_hpke_key);
3720 queue->key = queue_map_key;
3721 queue->address = in;
3722 queue->address_len = in_len;
3723 queue->sock = sock;
3725 boot_queue (queue);
3727 "booted queue with target %s\n",
3728 GNUNET_i2s (&queue->target));
3729 // queue->mq_awaits_continue = GNUNET_YES;
3730 queue->read_task =
3732 queue->sock,
3734 queue);
3735
3736
3738 "start kx mq_init\n");
3739
3741 queue->write_task =
3743 queue->sock,
3744 &queue_write,
3745 queue);
3746 }
3747
3748 return GNUNET_OK;
3749}
3750
3751
3760static int
3762 const struct GNUNET_HashCode *key,
3763 void *value)
3764{
3765 struct ListenTask *lt = value;
3766
3767 (void) cls;
3768 (void) key;
3769 if (NULL != lt->listen_task)
3770 {
3772 lt->listen_task = NULL;
3773 }
3774 if (NULL != lt->listen_sock)
3775 {
3777 lt->listen_sock = NULL;
3778 }
3779 GNUNET_free (lt);
3780 return GNUNET_OK;
3781}
3782
3783
3792static int
3794 const struct GNUNET_HashCode *target,
3795 void *value)
3796{
3797 struct Queue *queue = value;
3798
3799 (void) cls;
3800 (void) target;
3802 return GNUNET_OK;
3803}
3804
3805
3811static void
3812do_shutdown (void *cls)
3813{
3815 "Shutdown %s!\n",
3816 shutdown_running ? "running" : "not running");
3817
3819 return;
3820 else
3822
3823 while (NULL != proto_head)
3825 if (NULL != nat)
3826 {
3828 nat = NULL;
3829 }
3837 if (NULL != ch)
3838 {
3841 ch = NULL;
3842 }
3843 if (NULL != stats)
3844 {
3846 stats = NULL;
3847 }
3848 if (NULL != is)
3849 {
3851 is = NULL;
3852 }
3853 if (NULL != pils)
3854 {
3856 pils = NULL;
3857 }
3858 if (NULL != key_ring)
3859 {
3861 key_ring = NULL;
3862 }
3863 if (NULL != peerstore)
3864 {
3866 peerstore = NULL;
3867 }
3868 if (NULL != resolve_request_handle)
3869 {
3872 }
3874 "Shutdown done!\n");
3875}
3876
3877
3889static void
3890enc_notify_cb (void *cls,
3891 const struct GNUNET_PeerIdentity *sender,
3892 const struct GNUNET_MessageHeader *msg)
3893{
3894 (void) cls;
3895 (void) sender;
3896 (void) msg;
3897 GNUNET_break_op (0);
3898}
3899
3900
3914static void
3916 void **app_ctx,
3917 int add_remove,
3919 const struct sockaddr *addr,
3920 socklen_t addrlen)
3921{
3922 char *my_addr;
3924
3926 "nat address cb %s %s\n",
3927 add_remove ? "add" : "remove",
3928 GNUNET_a2s (addr, addrlen));
3929
3930 if (GNUNET_YES == add_remove)
3931 {
3933
3934 GNUNET_asprintf (&my_addr,
3935 "%s-%s",
3937 GNUNET_a2s (addr, addrlen));
3938 nt = GNUNET_NT_scanner_get_type (is, addr, addrlen);
3939 ai =
3941 my_addr,
3942 nt,
3944 GNUNET_free (my_addr);
3945 *app_ctx = ai;
3946 }
3947 else
3948 {
3949 ai = *app_ctx;
3951 *app_ctx = NULL;
3952 }
3953}
3954
3955
3959static void
3960add_addr (struct sockaddr *in, socklen_t in_len)
3961{
3962
3963 struct Addresses *saddrs;
3964
3966 "add address %s\n",
3967 GNUNET_a2s (in, in_len));
3968
3969 saddrs = GNUNET_new (struct Addresses);
3970 saddrs->addr = in;
3971 saddrs->addr_len = in_len;
3973
3975 "after add address %s\n",
3976 GNUNET_a2s (in, in_len));
3977
3979 "add address %s\n",
3980 GNUNET_a2s (saddrs->addr, saddrs->addr_len));
3981
3982 addrs_lens++;
3983}
3984
3985
3993static int
3994init_socket (struct sockaddr *addr,
3995 socklen_t in_len)
3996{
3997 struct sockaddr_storage in_sto;
3998 socklen_t sto_len;
3999 struct GNUNET_NETWORK_Handle *listen_sock;
4000 struct ListenTask *lt;
4001 int sockfd;
4002 struct GNUNET_HashCode h_sock;
4003
4004 if (NULL == addr)
4005 {
4007 "Address is NULL.\n");
4008 return GNUNET_SYSERR;
4009 }
4010
4012 "address %s\n",
4013 GNUNET_a2s (addr, in_len));
4014
4015 listen_sock =
4016 GNUNET_NETWORK_socket_create (addr->sa_family, SOCK_STREAM, IPPROTO_TCP);
4017 if (NULL == listen_sock)
4018 {
4020 return GNUNET_SYSERR;
4021 }
4022
4023 if (GNUNET_OK != GNUNET_NETWORK_socket_bind (listen_sock, addr, in_len))
4024 {
4026 GNUNET_NETWORK_socket_close (listen_sock);
4027 listen_sock = NULL;
4028 return GNUNET_SYSERR;
4029 }
4030
4031 if (GNUNET_OK !=
4032 GNUNET_NETWORK_socket_listen (listen_sock,
4033 5))
4034 {
4036 "listen");
4037 GNUNET_NETWORK_socket_close (listen_sock);
4038 listen_sock = NULL;
4039 return GNUNET_SYSERR;
4040 }
4041
4042 /* We might have bound to port 0, allowing the OS to figure it out;
4043 thus, get the real IN-address from the socket */
4044 sto_len = sizeof(in_sto);
4045
4046 if (0 != getsockname (GNUNET_NETWORK_get_fd (listen_sock),
4047 (struct sockaddr *) &in_sto,
4048 &sto_len))
4049 {
4050 memcpy (&in_sto, addr, in_len);
4051 sto_len = in_len;
4052 }
4053
4054 // addr = (struct sockaddr *) &in_sto;
4055 in_len = sto_len;
4057 "Bound to `%s'\n",
4058 GNUNET_a2s ((const struct sockaddr *) &in_sto, sto_len));
4059 if (NULL == stats)
4060 stats = GNUNET_STATISTICS_create ("communicator-tcp", cfg);
4061
4062 if (NULL == is)
4064
4065 /* start listening */
4066
4067 lt = GNUNET_new (struct ListenTask);
4068 lt->listen_sock = listen_sock;
4069
4071 listen_sock,
4072 &listen_cb,
4073 lt);
4074
4076 "creating hash\n");
4077 sockfd = GNUNET_NETWORK_get_fd (lt->listen_sock);
4078 GNUNET_CRYPTO_hash (&sockfd,
4079 sizeof(int),
4080 &h_sock);
4081
4083 "creating map\n");
4084 if (NULL == lt_map)
4086
4088 "creating map entry\n");
4091 &h_sock,
4092 lt,
4094
4096 "map entry created\n");
4097
4098 if (NULL == queue_map)
4100
4101 if (NULL == ch)
4106 &mq_init,
4107 NULL,
4109 NULL,
4110 NULL);
4111
4112 if (NULL == ch)
4113 {
4114 GNUNET_break (0);
4115 if (NULL != resolve_request_handle)
4118 return GNUNET_SYSERR;
4119 }
4120
4121 add_addr (addr, in_len);
4122 return GNUNET_OK;
4123
4124}
4125
4126
4130static void
4132{
4133 struct sockaddr **saddrs;
4134 socklen_t *saddr_lens;
4135 int i;
4136 size_t len;
4137
4139 "starting nat register!\n");
4140 len = 0;
4141 i = 0;
4142 saddrs = GNUNET_malloc ((addrs_lens) * sizeof(struct sockaddr *));
4143 saddr_lens = GNUNET_malloc ((addrs_lens) * sizeof(socklen_t));
4144 for (struct Addresses *pos = addrs_head; NULL != pos; pos = pos->next)
4145 {
4147 "registering address %s\n",
4148 GNUNET_a2s (pos->addr, pos->addr_len));
4149
4150 saddr_lens[i] = pos->addr_len;
4151 len += saddr_lens[i];
4152 saddrs[i] = GNUNET_memdup (pos->addr, saddr_lens[i]);
4153 i++;
4154 }
4155
4157 "registering addresses %lu %lu %lu %lu\n",
4158 (addrs_lens) * sizeof(struct sockaddr *),
4159 (addrs_lens) * sizeof(socklen_t),
4160 len,
4164 IPPROTO_TCP,
4165 addrs_lens,
4166 (const struct sockaddr **) saddrs,
4167 saddr_lens,
4170 NULL /* closure */);
4171 for (i = addrs_lens - 1; i >= 0; i--)
4172 GNUNET_free (saddrs[i]);
4173 GNUNET_free (saddrs);
4174 GNUNET_free (saddr_lens);
4175
4176 if (NULL == nat)
4177 {
4178 GNUNET_break (0);
4179 if (NULL != resolve_request_handle)
4182 }
4183}
4184
4185
4193static void
4195 const struct sockaddr *addr,
4196 socklen_t in_len)
4197{
4198 struct sockaddr_in *v4;
4199 struct sockaddr_in6 *v6;
4200 struct sockaddr *in;
4201
4202 (void) cls;
4203 if (NULL != addr)
4204 {
4205 if (AF_INET == addr->sa_family)
4206 {
4207 v4 = (struct sockaddr_in *) addr;
4208 in = tcp_address_to_sockaddr_numeric_v4 (&in_len, *v4, bind_port);// _global);
4209 }
4210 else if (AF_INET6 == addr->sa_family)
4211 {
4212 v6 = (struct sockaddr_in6 *) addr;
4213 in = tcp_address_to_sockaddr_numeric_v6 (&in_len, *v6, bind_port);// _global);
4214 }
4215 else
4216 {
4218 "Address family %u not suitable (not AF_INET %u nor AF_INET6 %u \n",
4219 addr->sa_family,
4220 AF_INET,
4221 AF_INET6);
4222 return;
4223 }
4224 init_socket (in, in_len);
4225 }
4226 else
4227 {
4229 "Address is NULL. This might be an error or the resolver finished resolving.\n");
4230 if (NULL == addrs_head)
4231 {
4233 "Resolver finished resolving, but we do not listen to an address!.\n");
4234 return;
4235 }
4236 nat_register ();
4237 }
4238}
4239
4240
4249static void
4250run (void *cls,
4251 char *const *args,
4252 const char *cfgfile,
4253 const struct GNUNET_CONFIGURATION_Handle *c)
4254{
4255 char *bindto;
4256 struct sockaddr *in;
4257 socklen_t in_len;
4258 struct sockaddr_in v4;
4259 struct sockaddr_in6 v6;
4260 char *start;
4261 unsigned int port;
4262 char dummy[2];
4263 char *rest = NULL;
4264 struct PortOnlyIpv4Ipv6 *po;
4265 socklen_t addr_len_ipv4;
4266 socklen_t addr_len_ipv6;
4267
4268 (void) cls;
4269
4271 memset (&v4,0,sizeof(struct sockaddr_in));
4272 memset (&v6,0,sizeof(struct sockaddr_in6));
4273 cfg = c;
4274 if (GNUNET_OK !=
4277 "BINDTO",
4278 &bindto))
4279 {
4282 "BINDTO");
4283 return;
4284 }
4285 if (GNUNET_OK !=
4288 "MAX_QUEUE_LENGTH",
4290 {
4292 }
4293 if (GNUNET_OK !=
4296 "REKEY_INTERVAL",
4298 {
4300 }
4301 if (GNUNET_OK !=
4304 "REKEY_MAX_BYTES",
4306 {
4308 }
4310 if ((GNUNET_NO == GNUNET_NETWORK_test_pf (PF_INET6)) ||
4311 (GNUNET_YES ==
4314 "DISABLE_V6")))
4315 {
4317 }
4319 GNUNET_assert (NULL != key_ring);
4320 pils = GNUNET_PILS_connect (cfg, NULL, NULL);
4321 GNUNET_assert (NULL != pils);
4323 if (NULL == peerstore)
4324 {
4325 GNUNET_free (bindto);
4326 GNUNET_break (0);
4328 return;
4329 }
4330
4332
4333 if (1 == sscanf (bindto, "%u%1s", &bind_port, dummy))
4334 {
4338 "address po %s\n",
4340 if (NULL != po->addr_ipv4)
4341 {
4343 }
4344 if (NULL != po->addr_ipv6)
4345 {
4348 }
4349 GNUNET_free (po);
4350 nat_register ();
4351 GNUNET_free (bindto);
4352 return;
4353 }
4354
4355 start = extract_address (bindto);
4356 // FIXME: check for NULL == start...
4357 if (1 == inet_pton (AF_INET, start, &v4.sin_addr))
4358 {
4359 bind_port = extract_port (bindto);
4360
4362 init_socket (in, in_len);
4363 nat_register ();
4365 GNUNET_free (bindto);
4366 return;
4367 }
4368
4369 if (1 == inet_pton (AF_INET6, start, &v6.sin6_addr))
4370 {
4371 bind_port = extract_port (bindto);
4373 init_socket (in, in_len);
4374 nat_register ();
4376 GNUNET_free (bindto);
4377 return;
4378 }
4379
4380 bind_port = extract_port (bindto);
4382 ":",
4383 &rest),
4384 AF_UNSPEC,
4387 &port);
4388
4389 GNUNET_free (bindto);
4391}
4392
4393
4401int
4402main (int argc, char *const *argv)
4403{
4404 static const struct GNUNET_GETOPT_CommandLineOption options[] = {
4406 };
4407 int ret;
4408
4410 "Starting tcp communicator\n");
4411
4412 ret = (GNUNET_OK ==
4414 argc,
4415 argv,
4416 "gnunet-communicator-tcp",
4417 _ ("GNUnet TCP communicator"),
4418 options,
4419 &run,
4420 NULL))
4421 ? 0
4422 : 1;
4423 return ret;
4424}
4425
4426
4427/* end of gnunet-communicator-tcp.c */
struct GNUNET_GETOPT_CommandLineOption options[]
Definition 002.c:5
struct GNUNET_MessageHeader * msg
Definition 005.c:2
int main()
Program to simulate results from GCP_get_desirability_of_path() for various plausible inputs.
static int start
Set if we are to start default services (including ARM).
Definition gnunet-arm.c:38
static int ret
Final status code.
Definition gnunet-arm.c:93
static int do_shutdown
Set to GNUNET_YES if we are shutting down.
static uint16_t port
Port number.
Definition gnunet-bcd.c:146
static void queue_finish(struct Queue *queue)
Append a 'finish' message to the outgoing transmission.
static void transmit_kx(struct Queue *queue, const struct GNUNET_CRYPTO_HpkeEncapsulation *c)
Generate and transmit our ephemeral key and the signature for the initial KX with the other peer.
static void boot_queue(struct Queue *queue)
Add the given queue to our internal data structure.
static unsigned int bind_port
The port the communicator should be assigned to.
static size_t try_handle_plaintext(struct Queue *queue)
Test if we have received a full message in plaintext.
static void pass_plaintext_to_core(struct Queue *queue, const void *plaintext, size_t plaintext_len)
We received plaintext_len bytes of plaintext on queue.
static struct sockaddr * tcp_address_to_sockaddr_numeric_v6(socklen_t *sock_len, struct sockaddr_in6 v6, unsigned int port)
Convert a struct sockaddr_in6 to astruct sockaddr *`.
#define TCP_QUEUE_GONE
Sentinel returned by try_handle_plaintext() to say that it destroyed the queue it was given.
#define COMMUNICATOR_ADDRESS_PREFIX
Address prefix used by the communicator.
static void mq_destroy(struct GNUNET_MQ_Handle *mq, void *impl_state)
Signature of functions implementing the destruction of a message queue.
static void finish_timeout_cb(void *cls)
We gave the queue a chance to flush its finish message and it did not take it (most likely because th...
#define ADDRESS_VALIDITY_PERIOD
How long do we believe our addresses to remain up (before the other peer should revalidate).
static struct PortOnlyIpv4Ipv6 * tcp_address_to_sockaddr_port_only(const char *bindto, unsigned int *port)
Convert TCP bind specification to a struct PortOnlyIpv4Ipv6 *
static void setup_in_cipher(const struct GNUNET_CRYPTO_HpkeEncapsulation *ephemeral, struct Queue *queue)
Setup cipher of queue for decryption.
static void eddsa_pub_to_hpke_key(const struct GNUNET_CRYPTO_EddsaPublicKey *edpk, struct GNUNET_CRYPTO_HpkePublicKey *pk)
#define INITIAL_CORE_KX_SIZE
Size of the initial core key exchange messages.
static void do_rekey(struct Queue *queue, const struct TCPRekey *rekey)
Handle rekey message on queue.
static void calculate_hmac(struct GNUNET_CRYPTO_AuthKey *hmac_secret, const void *buf, size_t buf_size, struct GNUNET_ShortHashCode *smac)
Compute mac over buf, and ratched the hmac_secret.
static struct ProtoQueue * create_proto_queue(struct GNUNET_NETWORK_Handle *sock, struct sockaddr *in, socklen_t addrlen)
static int init_socket(struct sockaddr *addr, socklen_t in_len)
This method launch network interactions for each address we like to bind to.
static void try_connection_reversal(void *cls, const struct sockaddr *addr, socklen_t addrlen)
static void eddsa_priv_to_hpke_key(const struct GNUNET_CRYPTO_EddsaPrivateKey *edpk, struct GNUNET_CRYPTO_HpkePrivateKey *pk)
static struct GNUNET_NT_InterfaceScanner * is
Network scanner to determine network types.
static void listen_cb(void *cls)
We have been notified that our listen socket has something to read.
static void rekey_monotime_cb(void *cls, const struct GNUNET_PEERSTORE_Record *record, const char *emsg)
Callback called by peerstore when records for GNUNET_PEERSTORE_TRANSPORT_TCP_COMMUNICATOR_REKEY where...
static int disable_v6
IPv6 disabled.
static struct GNUNET_CONTAINER_MultiHashMap * pending_reversals
Map of pending reversals.
static struct GNUNET_STATISTICS_Handle * stats
For logging statistics.
static void queue_destroy(struct Queue *queue)
Functions with this signature are called whenever we need to close a queue due to a disconnect or fai...
static const struct GNUNET_CONFIGURATION_Handle * cfg
Our configuration.
static void enc_notify_cb(void *cls, const struct GNUNET_PeerIdentity *sender, const struct GNUNET_MessageHeader *msg)
Function called when the transport service has received an acknowledgement for this communicator (!...
static void handshake_ack_monotime_store_cb(void *cls, int success)
Callback called when peerstore store operation for handshake ack monotime value is finished.
static struct GNUNET_PEERSTORE_Handle * peerstore
Database for peer's HELLOs.
static int pending_reversals_delete_it(void *cls, const struct GNUNET_HashCode *key, void *value)
static struct ProtoQueue * proto_tail
Protoqueues DLL tail.
static void queue_read_kx(void *cls)
Read from the socket of the queue until we have enough data to initialize the decryption logic and ca...
static int get_lt_delete_it(void *cls, const struct GNUNET_HashCode *key, void *value)
Iterator over all ListenTasks to clean up.
static void inject_rekey(struct Queue *queue)
Inject a struct TCPRekey message into the queue's plaintext buffer.
static struct GNUNET_TIME_Relative rekey_interval
The rekey interval.
#define NAT_TIMEOUT
How long until we give up on establishing an NAT connection? Must be > 4 RTT.
#define BUF_SIZE
Size of our IO buffers for ciphertext data.
static void pending_reversal_key(const struct sockaddr *in, const struct GNUNET_PeerIdentity *target, struct GNUNET_HashCode *key)
Compute the key under which a pending NAT reversal request to target at in is stored in pending_rever...
#define COMMUNICATOR_CONFIG_SECTION
Configuration section used by the communicator.
static struct GNUNET_CONTAINER_MultiHashMap * queue_map
Queues (map from peer identity to struct Queue)
static void proto_read_kx(void *cls)
Read from the socket of the proto queue until we have enough data to upgrade to full queue.
static void nat_address_cb(void *cls, void **app_ctx, int add_remove, enum GNUNET_NAT_AddressClass ac, const struct sockaddr *addr, socklen_t addrlen)
Signature of the callback passed to GNUNET_NAT_register() for a function to call whenever our set of ...
static struct sockaddr * tcp_address_to_sockaddr_numeric_v4(socklen_t *sock_len, struct sockaddr_in v4, unsigned int port)
Convert a struct sockaddr_in4 to astruct sockaddr *`.
static void check_and_remove_pending_reversal(struct sockaddr *in, sa_family_t sa_family, const struct GNUNET_PeerIdentity *sender)
We got a connection with sender at in, so a NAT reversal we may have requested for that peer has serv...
static void init_socket_resolv(void *cls, const struct sockaddr *addr, socklen_t in_len)
This method is the callback called by the resolver API, and wraps method init_socket.
static struct GNUNET_TRANSPORT_CommunicatorHandle * ch
Our environment.
#define FINISH_TIMEOUT
How long do we wait for a queue we are finishing to flush its GNUNET_MESSAGE_TYPE_COMMUNICATOR_TCP_FI...
static unsigned long long max_queue_length
Maximum queue length before we stop reading towards the transport service.
struct GNUNET_RESOLVER_RequestHandle * resolve_request_handle
Handle for DNS lookup of bindto address.
static void nat_register()
This method reads from the DLL addrs_head to register them at the NAT service.
static void setup_out_cipher(struct Queue *queue, struct GNUNET_ShortHashCode *dh)
Setup cipher for outgoing data stream based on target and our ephemeral private key.
static int addrs_lens
Number of addresses in the DLL for register at NAT service.
static void run(void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *c)
Setup communicator and launch network interactions.
static struct GNUNET_NAT_Handle * nat
Connection to NAT service.
static void pending_reversal_timeout(void *cls)
#define PROTO_QUEUE_TIMEOUT
How long do we wait until we must have received the initial KX?
static void queue_read(void *cls)
Queue read task.
static struct GNUNET_PILS_KeyRing * key_ring
For PILS.
#define REKEY_MAX_BYTES
How often do we rekey based on number of bytes transmitted? (additionally randomized).
static int get_queue_delete_it(void *cls, const struct GNUNET_HashCode *target, void *value)
Iterator over all message queues to clean up.
static void mq_cancel(struct GNUNET_MQ_Handle *mq, void *impl_state)
Implementation function that cancels the currently sent message.
#define INITIAL_KX_SIZE
Size of the initial key exchange message sent first in both directions.
static void handshake_ack_monotime_cb(void *cls, const struct GNUNET_PEERSTORE_Record *record, const char *emsg)
Callback called by peerstore when records for GNUNET_PEERSTORE_TRANSPORT_TCP_COMMUNICATOR_HANDSHAKE_A...
static int mq_init(void *cls, const struct GNUNET_PeerIdentity *peer, const char *address)
Function called by the transport service to initialize a message queue given address information abou...
static void proto_queue_write(void *cls)
We have been notified that our socket is ready to write.
static void handshake_monotime_store_cb(void *cls, int success)
Callback called when peerstore store operation for handshake monotime is finished.
static void send_challenge(struct GNUNET_CRYPTO_ChallengeNonceP challenge, struct Queue *queue)
Sending challenge with TcpConfirmationAck back to sender of ephemeral key.
static void rekey_monotime_store_cb(void *cls, int success)
Callback called when peerstore store operation for rekey monotime value is finished.
static char * extract_address(const char *bindto)
This Method extracts the address part of the BINDTO string.
static struct ProtoQueue * proto_head
Protoqueues DLL head.
static int shutdown_running
A flag indicating we are already doing a shutdown.
static int decrypt_and_check_tc(struct Queue *queue, struct TCPConfirmation *tc, char *ibuf)
We have received the first bytes from the other side on a queue.
#define DEFAULT_REKEY_INTERVAL
How often do we rekey based on time (at least)
static void queue_write(void *cls)
We have been notified that our socket is ready to write.
static void add_addr(struct sockaddr *in, socklen_t in_len)
This method adds addresses to the DLL, that are later register at the NAT service.
static void handshake_monotime_cb(void *cls, const struct GNUNET_PEERSTORE_Record *record, const char *emsg)
Callback called by peerstore when records for GNUNET_PEERSTORE_TRANSPORT_TCP_COMMUNICATOR_HANDSHAKE w...
static struct Addresses * addrs_head
Head of DLL with addresses we like to register at NAT service.
static struct sockaddr * tcp_address_to_sockaddr(const char *bindto, socklen_t *sock_len)
Convert TCP bind specification to a struct sockaddr *
static struct Addresses * addrs_tail
Head of DLL with addresses we like to register at NAT service.
static void setup_in_cipher_elligator(const struct GNUNET_CRYPTO_HpkeEncapsulation *c, struct Queue *queue)
Setup cipher of queue for decryption from an elligator representative.
#define DEFAULT_MAX_QUEUE_LENGTH
How many messages do we keep at most in the queue to the transport service before we start to drop (d...
static void mq_error(void *cls, enum GNUNET_MQ_Error error)
Generic error handler, called with the appropriate error code and the same closure specified at the c...
static unsigned int extract_port(const char *addr_and_port)
This Method extracts the port part of the BINDTO string.
static void mq_send(struct GNUNET_MQ_Handle *mq, const struct GNUNET_MessageHeader *msg, void *impl_state)
Signature of functions implementing the sending functionality of a message queue.
static struct GNUNET_PILS_Handle * pils
For PILS.
static void start_initial_kx_out(struct Queue *queue)
Initialize our key material for outgoing transmissions and inform the other peer about it.
static void setup_cipher(const struct GNUNET_ShortHashCode *prk, const struct GNUNET_PeerIdentity *pid, gcry_cipher_hd_t *cipher, struct GNUNET_CRYPTO_AuthKey *hmac_key)
Setup cipher based on shared secret dh and decrypting peer pid.
static void free_proto_queue(struct ProtoQueue *pq)
Closes socket and frees memory associated with pq.
static struct GNUNET_CONTAINER_MultiHashMap * lt_map
ListenTasks (map from socket to struct ListenTask)
static unsigned long long rekey_max_bytes
The rekey byte maximum.
static void core_read_finished_cb(void *cls, int success)
Core tells us it is done processing a message that transport received on a queue with status success.
static struct GNUNET_TRANSPORT_AddressIdentifier * ai
Handle to the operation that publishes our address.
static void record(void *cls, size_t data_size, const void *data)
Process recorded audio data.
static char * address
GNS address for this phone.
struct GNUNET_HashCode key
The key used in the DHT.
static struct in_addr dummy
Target "dummy" address of the packet we pretend to respond to.
struct GNUNET_CRYPTO_BlindablePrivateKey pk
Private key from command line option, or NULL.
struct GNUNET_SCHEDULER_Task * read_task
static void queue(const char *label, uint32_t rd_count, struct GNUNET_GNSRECORD_Data *rd, const struct Zone *zone)
Add hostname to the list of requests to be made.
static char * value
Value of the record to add/remove.
static uint32_t type
Type string converted to DNS type value.
static struct GNUNET_NAT_AUTO_Test * nt
Handle to a NAT test operation.
static struct GNUNET_PeerIdentity my_identity
Identity of this peer.
struct GNUNET_CRYPTO_EddsaPrivateKey my_private_key
The current private key.
commonly used definitions; globals in this file are exempt from the rule that the module name ("commo...
Core service; the main API for encrypted P2P communications.
API to the peerstore service.
struct GNUNET_PILS_Handle * GNUNET_PILS_connect(const struct GNUNET_CONFIGURATION_Handle *cfg, GNUNET_PILS_PidChangeCallback pid_change_cb, void *cls)
Connect to the PILS service.
Definition pils_api.c:624
void GNUNET_PILS_disconnect(struct GNUNET_PILS_Handle *handle)
Disconnect from the PILS service.
Definition pils_api.c:647
struct GNUNET_PILS_KeyRing * GNUNET_PILS_create_key_ring(const struct GNUNET_CONFIGURATION_Handle *cfg, GNUNET_SCHEDULER_TaskCallback init_cb, void *cls)
Create a key ring handle to use the current peer identity key.
Definition pils_api.c:1008
void GNUNET_PILS_destroy_key_ring(struct GNUNET_PILS_KeyRing *key_ring)
Destroy a key ring handle and free its memory.
Definition pils_api.c:1068
const struct GNUNET_PeerIdentity * GNUNET_PILS_get_identity(const struct GNUNET_PILS_Handle *handle)
Return the current peer identity of a given handle.
Definition pils_api.c:875
const struct GNUNET_CRYPTO_EddsaPrivateKey * GNUNET_PILS_key_ring_get_private_key(const struct GNUNET_PILS_KeyRing *key_ring)
Return the current private key of a given key ring handle.
Definition pils_api.c:1091
Constants for network protocols.
Functions related to doing DNS lookups.
#define GNUNET_SIGNATURE_PURPOSE_COMMUNICATOR_TCP_HANDSHAKE_ACK
Signature by a peer sending back the nonce received at initial handshake.
#define GNUNET_SIGNATURE_PURPOSE_COMMUNICATOR_TCP_REKEY
Signature used by TCP communicator rekey.
#define GNUNET_SIGNATURE_PURPOSE_COMMUNICATOR_TCP_HANDSHAKE
Signature used by TCP communicator handshake.
API to create, modify and access statistics.
API of the transport service towards the communicator processes.
void GNUNET_TRANSPORT_communicator_address_remove(struct GNUNET_TRANSPORT_AddressIdentifier *ai)
Notify transport service about an address that this communicator no longer provides for this peer.
int GNUNET_TRANSPORT_communicator_receive(struct GNUNET_TRANSPORT_CommunicatorHandle *handle, const struct GNUNET_PeerIdentity *sender, const struct GNUNET_MessageHeader *msg, struct GNUNET_TIME_Relative expected_addr_validity, GNUNET_TRANSPORT_MessageCompletedCallback cb, void *cb_cls)
Notify transport service that the communicator has received a message.
void GNUNET_TRANSPORT_communicator_mq_del(struct GNUNET_TRANSPORT_QueueHandle *qh)
Notify transport service that an MQ became unavailable due to a disconnect or timeout.
#define GNUNET_TRANSPORT_QUEUE_LENGTH_UNLIMITED
Queue length.
struct GNUNET_TRANSPORT_QueueHandle * GNUNET_TRANSPORT_communicator_mq_add(struct GNUNET_TRANSPORT_CommunicatorHandle *ch, const struct GNUNET_PeerIdentity *peer, const char *address, uint32_t mtu, uint64_t q_len, uint32_t priority, enum GNUNET_NetworkType nt, enum GNUNET_TRANSPORT_ConnectionStatus cs, struct GNUNET_MQ_Handle *mq)
Notify transport service that a MQ became available due to an "inbound" connection or because the com...
void GNUNET_TRANSPORT_communicator_disconnect(struct GNUNET_TRANSPORT_CommunicatorHandle *ch)
Disconnect from the transport service.
GNUNET_TRANSPORT_ConnectionStatus
Possible states of a connection.
struct GNUNET_TRANSPORT_CommunicatorHandle * GNUNET_TRANSPORT_communicator_connect(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *config_section_name, const char *addr_prefix, enum GNUNET_TRANSPORT_CommunicatorCharacteristics cc, GNUNET_TRANSPORT_CommunicatorMqInit mq_init, void *mq_init_cls, GNUNET_TRANSPORT_CommunicatorNotify notify_cb, void *notify_cb_cls, GNUNET_TRANSPORT_StartBurstNotify sb)
Connect to the transport service.
struct GNUNET_TRANSPORT_AddressIdentifier * GNUNET_TRANSPORT_communicator_address_add(struct GNUNET_TRANSPORT_CommunicatorHandle *ch, const char *address, enum GNUNET_NetworkType nt, struct GNUNET_TIME_Relative expiration)
Notify transport service about an address that this communicator provides for this peer.
void GNUNET_TRANSPORT_communicator_address_remove_all(struct GNUNET_TRANSPORT_CommunicatorHandle *ch)
Notify transport service that this communicator no longer provides all its addresses for this peer.
@ GNUNET_TRANSPORT_CC_RELIABLE
Transmission is reliabile (with ACKs), e.g.
@ GNUNET_TRANSPORT_CS_INBOUND
this is an inbound connection (communicator initiated)
@ GNUNET_TRANSPORT_CS_OUTBOUND
this is an outbound connection (transport initiated)
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_number(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, unsigned long long *number)
Get a configuration value that should be a number.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_yesno(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option)
Get a configuration value that should be in a set of "YES" or "NO".
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_time(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, struct GNUNET_TIME_Relative *time)
Get a configuration value that should be a relative time.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_string(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, char **value)
Get a configuration value that should be a string.
#define GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT
After how long do we consider a connection to a peer dead if we don't receive messages from the peer?
enum GNUNET_GenericReturnValue GNUNET_CRYPTO_eddsa_kem_decaps(const struct GNUNET_CRYPTO_EddsaPrivateKey *priv, const struct GNUNET_CRYPTO_HpkeEncapsulation *c, struct GNUNET_ShortHashCode *prk)
Decapsulate a key for a private EdDSA key.
uint64_t GNUNET_CRYPTO_random_u64(uint64_t max)
Generate a random unsigned 64-bit value.
enum GNUNET_GenericReturnValue GNUNET_CRYPTO_hpke_elligator_kem_encaps(const struct GNUNET_CRYPTO_HpkePublicKey *pkR, struct GNUNET_CRYPTO_HpkeEncapsulation *c, struct GNUNET_ShortHashCode *shared_secret)
Carries out ecdh encapsulation with given public key and the private key from a freshly created ephem...
enum GNUNET_GenericReturnValue GNUNET_CRYPTO_hpke_elligator_kem_decaps(const struct GNUNET_CRYPTO_HpkePrivateKey *skR, const struct GNUNET_CRYPTO_HpkeEncapsulation *c, struct GNUNET_ShortHashCode *shared_secret)
Carries out ecdh decapsulation with own private key and the representative of the received public key...
void GNUNET_CRYPTO_random_block(void *buffer, size_t length)
Fill block with a random values.
enum GNUNET_GenericReturnValue GNUNET_CRYPTO_eddsa_kem_encaps(const struct GNUNET_CRYPTO_EddsaPublicKey *pub, struct GNUNET_CRYPTO_HpkeEncapsulation *c, struct GNUNET_ShortHashCode *prk)
Encapsulate key material for a EdDSA public key.
#define GNUNET_CRYPTO_eddsa_sign(priv, ps, sig)
EdDSA sign a given block.
#define GNUNET_CRYPTO_eddsa_verify(purp, ps, sig, pub)
Verify EdDSA signature.
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
#define GNUNET_CONTAINER_DLL_insert(head, tail, element)
Insert an element at the head of a DLL.
#define GNUNET_GETOPT_OPTION_END
Marker for the end of the list of options.
void GNUNET_CRYPTO_hash(const void *block, size_t size, struct GNUNET_HashCode *ret)
Compute hash of a given block.
Definition crypto_hash.c:40
void GNUNET_CRYPTO_hmac(const struct GNUNET_CRYPTO_AuthKey *key, const void *plaintext, size_t plaintext_len, struct GNUNET_HashCode *hmac)
Calculate HMAC of a message (RFC 2104)
#define GNUNET_CRYPTO_hkdf_expand(result, out_len, prk,...)
HKDF-Expand using SHA256.
enum GNUNET_GenericReturnValue GNUNET_CONTAINER_multihashmap_contains(const struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key)
Check if the map contains any value under the given key (including values that are NULL).
int GNUNET_CONTAINER_multihashmap_iterate(struct GNUNET_CONTAINER_MultiHashMap *map, GNUNET_CONTAINER_MultiHashMapIteratorCallback it, void *it_cls)
Iterate over all entries in the map.
void * GNUNET_CONTAINER_multihashmap_get(const struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key)
Given a key find a value in the map matching the key.
enum GNUNET_GenericReturnValue GNUNET_CONTAINER_multihashmap_remove(struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key, const void *value)
Remove the given key-value pair from the map.
enum GNUNET_GenericReturnValue GNUNET_CONTAINER_multihashmap_put(struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key, void *value, enum GNUNET_CONTAINER_MultiHashMapOption opt)
Store a key-value pair in the map.
unsigned int GNUNET_CONTAINER_multihashmap_size(const struct GNUNET_CONTAINER_MultiHashMap *map)
Get the number of key-value pairs in the map.
void GNUNET_CONTAINER_multihashmap_destroy(struct GNUNET_CONTAINER_MultiHashMap *map)
Destroy a hash map.
struct GNUNET_CONTAINER_MultiHashMap * GNUNET_CONTAINER_multihashmap_create(unsigned int len, int do_not_copy_keys)
Create a multi hash map.
@ GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE
Allow multiple values with the same key.
@ GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY
There must only be one value per key; storing a value should fail if a value under the same key alrea...
#define GNUNET_NETWORK_STRUCT_BEGIN
Define as empty, GNUNET_PACKED should suffice, but this won't work on W32.
uint16_t type
The type of the message (GNUNET_MESSAGE_TYPE_XXXX), in big-endian format.
#define GNUNET_log(kind,...)
void GNUNET_CRYPTO_hash_context_read(struct GNUNET_HashContext *hc, const void *buf, size_t size)
Add data to be hashed.
#define GNUNET_CRYPTO_kdf_arg_string(d)
enum GNUNET_GenericReturnValue GNUNET_CRYPTO_hpke_sk_to_x25519(const struct GNUNET_CRYPTO_BlindablePrivateKey *sk, struct GNUNET_CRYPTO_HpkePrivateKey *sk_enc)
Convert a GNUnet identity key to a key sutiable for HPKE (X25519)
#define GNUNET_NETWORK_STRUCT_END
Define as empty, GNUNET_PACKED should suffice, but this won't work on W32;.
#define GNUNET_memcmp(a, b)
Compare memory in a and b, where both must be of the same pointer type.
void GNUNET_CRYPTO_hash_context_finish(struct GNUNET_HashContext *hc, struct GNUNET_HashCode *r_hash)
Finish the hash computation.
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
GNUNET_GenericReturnValue
Named constants for return values.
enum GNUNET_GenericReturnValue GNUNET_CRYPTO_hpke_pk_to_x25519(const struct GNUNET_CRYPTO_BlindablePublicKey *pk, struct GNUNET_CRYPTO_HpkePublicKey *pk_enc)
Convert a GNUnet identity key to a key sutiable for HPKE (X25519)
#define GNUNET_MIN(a, b)
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format.
struct GNUNET_HashContext * GNUNET_CRYPTO_hash_context_start(void)
Start incremental hashing operation.
@ GNUNET_PUBLIC_KEY_TYPE_EDDSA
EDDSA identity.
@ GNUNET_OK
@ GNUNET_YES
@ GNUNET_NO
@ GNUNET_SYSERR
#define GNUNET_break_op(cond)
Use this for assertion violations caused by other peers (i.e.
const char * GNUNET_i2s(const struct GNUNET_PeerIdentity *pid)
Convert a peer identity to a string (for printing debug messages).
const char * GNUNET_e2s(const struct GNUNET_CRYPTO_EcdhePublicKey *p)
Convert a public key value to a string (for printing debug messages).
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur.
const char * GNUNET_a2s(const struct sockaddr *addr, socklen_t addrlen)
Convert a "struct sockaddr*" (IPv4 or IPv6 address) to a string (for printing debug messages).
void GNUNET_log_config_missing(enum GNUNET_ErrorType kind, const char *section, const char *option)
Log error message about missing configuration option.
#define GNUNET_log_strerror(level, cmd)
Log an error message at log-level 'level' that indicates a failure of the command 'cmd' with the mess...
const char * GNUNET_p2s(const struct GNUNET_CRYPTO_EddsaPublicKey *p)
Convert a public key value to a string (for printing debug messages).
@ GNUNET_ERROR_TYPE_WARNING
@ GNUNET_ERROR_TYPE_ERROR
@ GNUNET_ERROR_TYPE_DEBUG
@ GNUNET_ERROR_TYPE_INFO
int int GNUNET_asprintf(char **buf, const char *format,...) __attribute__((format(printf
Like asprintf, just portable.
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
#define GNUNET_malloc(size)
Wrapper around malloc.
#define GNUNET_free(ptr)
Wrapper around free.
#define GNUNET_memdup(buf, size)
Allocate and initialize a block of memory.
GNUNET_MQ_Error
Error codes for the queue.
struct GNUNET_MQ_Handle * GNUNET_MQ_queue_for_callbacks(GNUNET_MQ_SendImpl send, GNUNET_MQ_DestroyImpl destroy, GNUNET_MQ_CancelImpl cancel, void *impl_state, const struct GNUNET_MQ_MessageHandler *handlers, GNUNET_MQ_ErrorHandler error_handler, void *cls)
Create a message queue for the specified handlers.
Definition mq.c:514
void GNUNET_MQ_impl_send_continue(struct GNUNET_MQ_Handle *mq)
Call the send implementation for the next queued message, if any.
Definition mq.c:469
int GNUNET_NAT_request_reversal(struct GNUNET_NAT_Handle *nh, const struct sockaddr_in *local_sa, const struct sockaddr_in *remote_sa)
We learned about a peer (possibly behind NAT) so run the gnunet-nat-client to send dummy ICMP respons...
Definition nat_api.c:675
struct GNUNET_NAT_Handle * GNUNET_NAT_register(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *config_section, uint8_t proto, unsigned int num_addrs, const struct sockaddr **addrs, const socklen_t *addrlens, GNUNET_NAT_AddressCallback address_callback, GNUNET_NAT_ReversalCallback reversal_callback, void *callback_cls)
Attempt to enable port redirection and detect public IP address contacting UPnP or NAT-PMP routers on...
Definition nat_api.c:366
void GNUNET_NAT_unregister(struct GNUNET_NAT_Handle *nh)
Stop port redirection and public IP address detection for the given handle.
Definition nat_api.c:703
GNUNET_NAT_AddressClass
Some addresses contain sensitive information or are not suitable for global distribution.
struct GNUNET_NETWORK_Handle * GNUNET_NETWORK_socket_accept(const struct GNUNET_NETWORK_Handle *desc, struct sockaddr *address, socklen_t *address_len)
Accept a new connection on a socket.
Definition network.c:392
enum GNUNET_GenericReturnValue GNUNET_NETWORK_socket_close(struct GNUNET_NETWORK_Handle *desc)
Close a socket.
Definition network.c:508
int GNUNET_NETWORK_get_fd(const struct GNUNET_NETWORK_Handle *desc)
Return file descriptor for this network handle.
Definition network.c:1000
ssize_t GNUNET_NETWORK_socket_recv(const struct GNUNET_NETWORK_Handle *desc, void *buffer, size_t length)
Read data from a connected socket (always non-blocking).
Definition network.c:716
struct GNUNET_NETWORK_Handle * GNUNET_NETWORK_socket_create(int domain, int type, int protocol)
Create a new socket.
Definition network.c:832
enum GNUNET_GenericReturnValue GNUNET_NETWORK_socket_connect(const struct GNUNET_NETWORK_Handle *desc, const struct sockaddr *address, socklen_t address_len)
Connect a socket to some remote address.
Definition network.c:601
ssize_t GNUNET_NETWORK_socket_send(const struct GNUNET_NETWORK_Handle *desc, const void *buffer, size_t length)
Send data (always non-blocking).
Definition network.c:737
enum GNUNET_GenericReturnValue GNUNET_NETWORK_test_pf(int pf)
Test if the given protocol family is supported by this system.
Definition network.c:79
enum GNUNET_GenericReturnValue GNUNET_NETWORK_socket_bind(struct GNUNET_NETWORK_Handle *desc, const struct sockaddr *address, socklen_t address_len)
Bind a socket to a particular address.
Definition network.c:439
enum GNUNET_GenericReturnValue GNUNET_NETWORK_socket_listen(const struct GNUNET_NETWORK_Handle *desc, int backlog)
Listen on a socket.
Definition network.c:651
GNUNET_NetworkType
Types of networks (with separate quotas) we support.
void GNUNET_NT_scanner_done(struct GNUNET_NT_InterfaceScanner *is)
Terminate interface scanner.
Definition nt.c:428
struct GNUNET_NT_InterfaceScanner * GNUNET_NT_scanner_init(void)
Initialize the address characterization client handle.
Definition nt.c:407
enum GNUNET_NetworkType GNUNET_NT_scanner_get_type(struct GNUNET_NT_InterfaceScanner *is, const struct sockaddr *addr, socklen_t addrlen)
Returns where the address is located: loopback, LAN or WAN.
Definition nt.c:309
const struct GNUNET_OS_ProjectData * GNUNET_OS_project_data_gnunet(void)
Return default project data used by 'libgnunetutil' for GNUnet.
struct GNUNET_PEERSTORE_IterateContext * GNUNET_PEERSTORE_iteration_start(struct GNUNET_PEERSTORE_Handle *h, const char *sub_system, const struct GNUNET_PeerIdentity *peer, const char *key, GNUNET_PEERSTORE_Processor callback, void *callback_cls)
Iterate over peerstore entries.
void GNUNET_PEERSTORE_iteration_next(struct GNUNET_PEERSTORE_IterateContext *ic, uint64_t limit)
Continue an iteration.
void GNUNET_PEERSTORE_store_cancel(struct GNUNET_PEERSTORE_StoreContext *sc)
Cancel a store request.
void GNUNET_PEERSTORE_disconnect(struct GNUNET_PEERSTORE_Handle *h)
Disconnect from the PEERSTORE service.
struct GNUNET_PEERSTORE_Handle * GNUNET_PEERSTORE_connect(const struct GNUNET_CONFIGURATION_Handle *cfg)
Connect to the PEERSTORE service.
#define GNUNET_PEERSTORE_TRANSPORT_TCP_COMMUNICATOR_HANDSHAKE
Key used to store sender's monotonic time from handshake message.
struct GNUNET_PEERSTORE_StoreContext * GNUNET_PEERSTORE_store(struct GNUNET_PEERSTORE_Handle *h, const char *sub_system, const struct GNUNET_PeerIdentity *peer, const char *key, const void *value, size_t size, struct GNUNET_TIME_Absolute expiry, enum GNUNET_PEERSTORE_StoreOption options, GNUNET_PEERSTORE_Continuation cont, void *cont_cls)
Store a new entry in the PEERSTORE.
#define GNUNET_PEERSTORE_TRANSPORT_TCP_COMMUNICATOR_HANDSHAKE_ACK
Key used to store sender's monotonic time from handshake ack message.
#define GNUNET_PEERSTORE_TRANSPORT_TCP_COMMUNICATOR_REKEY
Key used to store sender's monotonic time from rekey message.
void GNUNET_PEERSTORE_iteration_stop(struct GNUNET_PEERSTORE_IterateContext *ic)
Cancel an iteration.
@ GNUNET_PEERSTORE_STOREOPTION_REPLACE
Delete any previous values for the given key before storing the given value.
enum GNUNET_GenericReturnValue GNUNET_PROGRAM_run(const struct GNUNET_OS_ProjectData *pd, int argc, char *const *argv, const char *binaryName, const char *binaryHelp, const struct GNUNET_GETOPT_CommandLineOption *options, GNUNET_PROGRAM_Main task, void *task_cls)
Run a standard GNUnet command startup sequence (initialize loggers and configuration,...
Definition program.c:406
#define GNUNET_MESSAGE_TYPE_COMMUNICATOR_TCP_CONFIRMATION_ACK
TCP communicator confirmation ack.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_TCP_NAT_PROBE
TCP NAT probe message, send from NAT'd peer to other peer to establish bi-directional communication.
#define GNUNET_MESSAGE_TYPE_COMMUNICATOR_TCP_FINISH
TCP communicator end of stream.
#define GNUNET_MESSAGE_TYPE_COMMUNICATOR_TCP_BOX
TCP communicator payload box.
#define GNUNET_MESSAGE_TYPE_COMMUNICATOR_TCP_REKEY
TCP communicator rekey message.
struct GNUNET_RESOLVER_RequestHandle * GNUNET_RESOLVER_ip_get(const char *hostname, int af, struct GNUNET_TIME_Relative timeout, GNUNET_RESOLVER_AddressCallback callback, void *callback_cls)
Convert a string to one or more IP addresses.
void GNUNET_RESOLVER_request_cancel(struct GNUNET_RESOLVER_RequestHandle *rh)
Cancel a request that is still pending with the resolver.
void GNUNET_SCHEDULER_shutdown(void)
Request the shutdown of a scheduler.
Definition scheduler.c:572
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_read_net(struct GNUNET_TIME_Relative delay, struct GNUNET_NETWORK_Handle *rfd, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay or when the specified file descriptor is ready f...
Definition scheduler.c:1517
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_write_net(struct GNUNET_TIME_Relative delay, struct GNUNET_NETWORK_Handle *wfd, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay or when the specified file descriptor is ready f...
Definition scheduler.c:1588
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_shutdown(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run on shutdown, that is when a CTRL-C signal is received,...
Definition scheduler.c:1345
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition scheduler.c:986
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_now(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run as soon as possible.
Definition scheduler.c:1310
void(* GNUNET_SCHEDULER_TaskCallback)(void *cls)
Signature of the main function of a task.
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_delayed(struct GNUNET_TIME_Relative delay, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay.
Definition scheduler.c:1283
struct GNUNET_STATISTICS_Handle * GNUNET_STATISTICS_create(const char *subsystem, const struct GNUNET_CONFIGURATION_Handle *cfg)
Get handle for the statistics service.
void GNUNET_STATISTICS_set(struct GNUNET_STATISTICS_Handle *handle, const char *name, uint64_t value, int make_persistent)
Set statistic value for the peer.
void GNUNET_STATISTICS_update(struct GNUNET_STATISTICS_Handle *handle, const char *name, int64_t delta, int make_persistent)
Set statistic value for the peer.
void GNUNET_STATISTICS_destroy(struct GNUNET_STATISTICS_Handle *h, int sync_first)
Destroy a handle (free all state associated with it).
#define GNUNET_TIME_UNIT_FOREVER_REL
Constant used to specify "forever".
struct GNUNET_TIME_Relative GNUNET_TIME_absolute_get_remaining(struct GNUNET_TIME_Absolute future)
Given a timestamp in the future, how much time remains until then?
Definition time.c:406
const char * GNUNET_STRINGS_relative_time_to_string(struct GNUNET_TIME_Relative delta, int do_round)
Give relative time in human-readable fancy format.
Definition strings.c:610
#define GNUNET_TIME_UNIT_MINUTES
One minute.
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_ntoh(struct GNUNET_TIME_AbsoluteNBO a)
Convert absolute time from network byte order.
Definition time.c:737
struct GNUNET_TIME_Absolute GNUNET_TIME_relative_to_absolute(struct GNUNET_TIME_Relative rel)
Convert relative time to an absolute time in the future.
Definition time.c:316
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_get_monotonic(const struct GNUNET_CONFIGURATION_Handle *cfg)
Obtain the current time and make sure it is monotonically increasing.
Definition time.c:860
struct GNUNET_TIME_AbsoluteNBO GNUNET_TIME_absolute_hton(struct GNUNET_TIME_Absolute a)
Convert absolute time to network byte order.
Definition time.c:636
const char * GNUNET_STRINGS_absolute_time_to_string(struct GNUNET_TIME_Absolute t)
Like asctime, except for GNUnet time.
Definition strings.c:671
#define GNUNET_TIME_UNIT_FOREVER_ABS
Constant used to specify "forever".
#define max(x, y)
static unsigned int size
Size of the "table".
Definition peer.c:68
#define _(String)
GNU gettext support macro.
Definition platform.h:179
static struct GNUNET_MQ_Handle * mq
Our connection to the resolver service, created on-demand, but then persists until error or shutdown.
static struct GNUNET_SCHEDULER_TaskContext tc
Task context of the current task.
Definition scheduler.c:436
DLL to store the addresses we like to register at NAT service.
struct Addresses * next
Kept in a DLL.
struct Addresses * prev
Kept in a DLL.
struct sockaddr * addr
Address we like to register at NAT service.
socklen_t addr_len
Length of address we like to register at NAT service.
Internal representation of the hash map.
type for (message) authentication keys
A private key for an identity as per LSD0001.
An identity key as per LSD0001.
Type of a nonce used for challenges.
Public ECC key (always for Curve25519) encoded in a format suitable for network transmission and encr...
Private ECC key encoded for transmission.
Public ECC key (always for curve Ed25519) encoded in a format suitable for network transmission and E...
an ECC signature using EdDSA.
HPKE DHKEM encapsulation (X25519) See RFC 9180.
A public key used for decryption.
A public key used for encryption.
header of what an ECC signature signs this must be followed by "size - 8" bytes of the actual signed ...
uint32_t purpose
What does this signature vouch for? This must contain a GNUNET_SIGNATURE_PURPOSE_XXX constant (from g...
uint32_t size
How many bytes does this signature sign? (including this purpose header); in network byte order (!...
Definition of a command line option.
A 512-bit hashcode.
Handle to a message queue.
Definition mq.c:87
Header for all communications.
Handle for active NAT registrations.
Definition nat_api.c:72
handle to a socket
Definition network.c:53
Handle to the interface scanner.
Definition nt.c:104
Handle to the PEERSTORE service.
Context for a iterate request.
Context for a store request.
A handle for the PILS service.
Definition pils_api.c:86
A simplified handle for using the peer identity key.
Definition pils_api.c:149
The identity of the host (wraps the signing key of the peer).
struct GNUNET_CRYPTO_EddsaPublicKey public_key
Handle to a request given to the resolver.
Entry in list of pending tasks.
Definition scheduler.c:141
Handle for the service.
A 256-bit hashcode.
Time for absolute time used by GNUnet, in microseconds and in network byte order.
Time for absolute times used by GNUnet, in microseconds.
uint64_t abs_value_us
The actual value.
Time for relative time used by GNUnet, in microseconds.
uint64_t rel_value_us
The actual value.
Internal representation of an address a communicator is currently providing for the transport service...
Opaque handle to the transport service for communicators.
struct GNUNET_MQ_Handle * mq
Queue to talk to the transport service.
Handle returned to identify the internal data structure the transport API has created to manage a mes...
Struct to use as closure.
struct GNUNET_NETWORK_Handle * listen_sock
Listen socket.
struct GNUNET_SCHEDULER_Task * listen_task
ID of listen task.
Struct for pending nat reversals.
struct sockaddr * in
Address the reversal was send to.
struct GNUNET_SCHEDULER_Task * timeout_task
struct GNUNET_PeerIdentity target
To whom are we like to talk to.
In case of port only configuration we like to bind to ipv4 and ipv6 addresses.
struct sockaddr * addr_ipv4
Ipv4 address we like to bind to.
struct sockaddr * addr_ipv6
Ipv6 address we like to bind to.
socklen_t addr_len_ipv6
Length of ipv6 address.
socklen_t addr_len_ipv4
Length of ipv4 address.
Handle for an incoming connection where we do not yet have enough information to setup a full queue.
socklen_t address_len
Length of the address.
struct GNUNET_SCHEDULER_Task * write_task
ID of write task for this connection.
char write_buf[sizeof(struct TCPNATProbeMessage)]
buffer for writing struct TCPNATProbeMessage to network.
struct GNUNET_NETWORK_Handle * listen_sock
Listen socket.
size_t ibuf_off
Current offset for reading into ibuf.
struct GNUNET_TIME_Absolute timeout
Timeout for this protoqueue.
struct GNUNET_NETWORK_Handle * sock
socket that we transmit all data with on this queue
struct sockaddr * address
Address of the other peer.
struct ProtoQueue * prev
Kept in a DLL.
char ibuf[(sizeof(struct GNUNET_CRYPTO_EcdhePublicKey)+sizeof(struct TCPConfirmation))]
Buffer for reading all the information we need to upgrade from protoqueue to queue.
size_t write_off
Offset of the buffer?
struct GNUNET_SCHEDULER_Task * read_task
ID of read task for this connection.
struct ProtoQueue * next
Kept in a DLL.
Handle for a queue.
unsigned int backpressure
How may messages did we pass from this queue to CORE for which we have yet to receive an acknowledgem...
struct GNUNET_NETWORK_Handle * sock
socket that we transmit all data with on this queue
struct GNUNET_PEERSTORE_IterateContext * handshake_ack_monotime_get
Iteration Context for retrieving the monotonic time send with the handshake ack.
int rekeyed
GNUNET_YES if we just rekeyed and must thus possibly re-decrypt ciphertext.
struct GNUNET_CRYPTO_ChallengeNonceP challenge
Challenge value used to protect against replay attack, if there is no stored monotonic time value.
size_t unverified_size
Size of data received without KX challenge played back.
struct GNUNET_SCHEDULER_Task * finish_task
ID of the task that tears this queue down once we gave up on flushing the GNUNET_MESSAGE_TYPE_COMMUNI...
struct GNUNET_TRANSPORT_QueueHandle * qh
handle for this queue with the ch.
int finishing
Did we enqueue a finish message and are closing down the queue?
int initial_core_kx_done
Has the initial (core) handshake already happened?
struct GNUNET_HashCode key
Key in hash map.
socklen_t address_len
Length of the address.
struct GNUNET_CRYPTO_AuthKey in_hmac
Shared secret for HMAC verification on incoming data.
struct GNUNET_MQ_Handle * mq
Message queue we are providing for the ch.
unsigned long long bytes_in_queue
Number of bytes we currently have in our write queue.
char pread_buf[UINT16_MAX+1+sizeof(struct TCPBox)]
Plaintext buffer for decrypted plaintext.
int destroyed
Did we technically destroy this queue, but kept the allocation around because of backpressure not bei...
struct GNUNET_PEERSTORE_StoreContext * rekey_monotime_sc
Store Context for retrieving the monotonic time send with key for rekeying.
size_t cwrite_off
At which offset in the ciphertext write buffer should we append more ciphertext from reading next?
struct GNUNET_PEERSTORE_IterateContext * rekey_monotime_get
Iteration Context for retrieving the monotonic time send with key for rekeying.
char cread_buf[(2 *64 *1024+sizeof(struct TCPBox))]
Buffer for reading ciphertext from network into.
struct GNUNET_CRYPTO_HpkePublicKey target_hpke_key
To whom are we talking to.
enum GNUNET_NetworkType nt
Which network type does this queue use?
struct GNUNET_CRYPTO_ChallengeNonceP challenge_received
Challenge value received.
uint64_t rekey_left_bytes
How many more bytes may we sent with the current out_cipher before we should rekey?
int mq_awaits_continue
Is MQ awaiting a GNUNET_MQ_impl_send_continue() call?
gcry_cipher_hd_t in_cipher
cipher for decryption of incoming data.
struct GNUNET_PEERSTORE_StoreContext * handshake_ack_monotime_sc
Store Context for retrieving the monotonic time send with the handshake ack.
struct GNUNET_SCHEDULER_Task * write_task
ID of write task for this connection.
size_t pwrite_off
At which offset in the plaintext output buffer should we append more plaintext for encryption next?
struct GNUNET_TIME_Absolute timeout
Timeout for this queue.
size_t cread_off
At which offset in the ciphertext read buffer should we append more ciphertext for transmission next?
struct GNUNET_TIME_Absolute rekey_time
Until what time may we sent with the current out_cipher before we should rekey?
struct GNUNET_PeerIdentity target
To whom are we talking to.
char cwrite_buf[(2 *64 *1024+sizeof(struct TCPBox))]
buffer for writing ciphertext to network.
struct GNUNET_PEERSTORE_StoreContext * handshake_monotime_sc
Store Context for retrieving the monotonic time send with the handshake.
size_t pread_off
At which offset in the plaintext input buffer should we append more plaintext from decryption next?
struct GNUNET_SCHEDULER_Task * read_task
ID of read task for this connection.
enum GNUNET_TRANSPORT_ConnectionStatus cs
The connection status of this queue.
gcry_cipher_hd_t out_cipher
cipher for encryption of outgoing data.
char pwrite_buf[UINT16_MAX+1+sizeof(struct TCPBox)]
Plaintext buffer for messages to be encrypted.
struct GNUNET_PEERSTORE_IterateContext * handshake_monotime_get
Iteration Context for retrieving the monotonic time send with the handshake.
struct GNUNET_NETWORK_Handle * listen_sock
Listen socket.
struct sockaddr * address
Address of the other peer.
struct GNUNET_CRYPTO_AuthKey out_hmac
Shared secret for HMAC generation on outgoing data, ratcheted after each operation.
struct GNUNET_TIME_AbsoluteNBO handshake_ack_monotonic_time
Monotonic time value for handshake ack message.
struct GNUNET_TIME_AbsoluteNBO rekey_monotonic_time
Monotonic time value for rekey message.
struct GNUNET_TIME_AbsoluteNBO handshake_monotonic_time
Monotonic time value for handshake message.
TCP message box.
struct GNUNET_MessageHeader header
Type is GNUNET_MESSAGE_TYPE_COMMUNICATOR_TCP_BOX.
struct GNUNET_ShortHashCode hmac
HMAC for the following encrypted message.
Ack for the encrypted continuation of TCP initial handshake.
struct GNUNET_TIME_AbsoluteNBO monotonic_time
Monotonic time of sender, to possibly help detect replay attacks (if receiver persists times by sende...
struct GNUNET_CRYPTO_EddsaSignature sender_sig
Sender's signature of type GNUNET_SIGNATURE_PURPOSE_COMMUNICATOR_TCP_HANDSHAKE_ACK.
struct GNUNET_CRYPTO_ChallengeNonceP challenge
Challenge value used to protect against replay attack, if there is no stored monotonic time value.
struct GNUNET_MessageHeader header
Type is GNUNET_MESSAGE_TYPE_COMMUNICATOR_TCP_CONFIRMATION_ACK.
struct GNUNET_PeerIdentity sender
Sender's identity.
Encrypted continuation of TCP initial handshake.
struct GNUNET_TIME_AbsoluteNBO monotonic_time
Monotonic time of sender, to possibly help detect replay attacks (if receiver persists times by sende...
struct GNUNET_CRYPTO_EddsaSignature sender_sig
Sender's signature of type GNUNET_SIGNATURE_PURPOSE_COMMUNICATOR_TCP_HANDSHAKE.
struct GNUNET_PeerIdentity sender
Sender's identity.
struct GNUNET_CRYPTO_ChallengeNonceP challenge
Challenge value used to protect against replay attack, if there is no stored monotonic time value.
struct GNUNET_MessageHeader header
Type is GNUNET_MESSAGE_TYPE_COMMUNICATOR_TCP_FINISH.
struct GNUNET_ShortHashCode hmac
HMAC for the following encrypted message.
Basically a WELCOME message, but with the purpose of giving the waiting peer a client handle to use.
struct GNUNET_PeerIdentity clientIdentity
Identity of the sender of the message.
struct GNUNET_MessageHeader header
Type is GNUNET_MESSAGE_TYPE_TRANSPORT_TCP_NAT_PROBE.
TCP rekey message box.
struct GNUNET_TIME_AbsoluteNBO monotonic_time
Monotonic time of sender, to possibly help detect replay attacks (if receiver persists times by sende...
struct GNUNET_CRYPTO_EddsaSignature sender_sig
Sender's signature of type GNUNET_SIGNATURE_PURPOSE_COMMUNICATOR_TCP_REKEY.
struct GNUNET_CRYPTO_HpkeEncapsulation ephemeral
New ephemeral key.
struct GNUNET_ShortHashCode hmac
HMAC for the following encrypted message.
struct GNUNET_MessageHeader header
Type is GNUNET_MESSAGE_TYPE_COMMUNICATOR_TCP_REKEY.
Signature we use to verify that the ack from the receiver of the ephemeral key was really send by the...
struct GNUNET_PeerIdentity sender
Identity of the inititor of the TCP connection (TCP client).
struct GNUNET_CRYPTO_ChallengeNonceP challenge
Challenge value used to protect against replay attack, if there is no stored monotonic time value.
struct GNUNET_PeerIdentity receiver
Presumed identity of the target of the TCP connection (TCP server)
struct GNUNET_CRYPTO_SignaturePurpose purpose
Purpose must be GNUNET_SIGNATURE_PURPOSE_COMMUNICATOR_TCP_HANDSHAKE_ACK.
struct GNUNET_TIME_AbsoluteNBO monotonic_time
Monotonic time of sender, to possibly help detect replay attacks (if receiver persists times by sende...
Signature we use to verify that the ephemeral key was really chosen by the specified sender.
struct GNUNET_CRYPTO_ChallengeNonceP challenge
Challenge value used to protect against replay attack, if there is no stored monotonic time value.
struct GNUNET_CRYPTO_HpkeEncapsulation ephemeral
Ephemeral key used by the sender (as Elligator representative).
struct GNUNET_PeerIdentity sender
Identity of the inititor of the TCP connection (TCP client).
struct GNUNET_CRYPTO_SignaturePurpose purpose
Purpose must be GNUNET_SIGNATURE_PURPOSE_COMMUNICATOR_TCP_HANDSHAKE.
struct GNUNET_TIME_AbsoluteNBO monotonic_time
Monotonic time of sender, to possibly help detect replay attacks (if receiver persists times by sende...
struct GNUNET_PeerIdentity receiver
Presumed identity of the target of the TCP connection (TCP server)
Signature we use to verify that the ephemeral key was really chosen by the specified sender.
struct GNUNET_CRYPTO_HpkeEncapsulation ephemeral
Ephemeral key used by the sender.
struct GNUNET_CRYPTO_SignaturePurpose purpose
Purpose must be GNUNET_SIGNATURE_PURPOSE_COMMUNICATOR_TCP_REKEY.
struct GNUNET_PeerIdentity sender
Identity of the inititor of the TCP connection (TCP client).
struct GNUNET_PeerIdentity receiver
Presumed identity of the target of the TCP connection (TCP server)
struct GNUNET_TIME_AbsoluteNBO monotonic_time
Monotonic time of sender, to possibly help detect replay attacks (if receiver persists times by sende...