aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2009-07-12 15:31:11 +0000
committerChristian Grothoff <christian@grothoff.org>2009-07-12 15:31:11 +0000
commit868126cd639e63cd6f4db19a19e49778fc67e0ad (patch)
tree05bbcc2c6cef1c3a9eec7e799d265f138cf9685c
parent0700c60ef320c8ccbd417833441697c64d6c525c (diff)
downloadgnunet-868126cd639e63cd6f4db19a19e49778fc67e0ad.tar.gz
gnunet-868126cd639e63cd6f4db19a19e49778fc67e0ad.zip
improving HELLO validation by transports
-rw-r--r--src/transport/gnunet-service-transport.c514
-rw-r--r--src/transport/plugin_transport.h77
-rw-r--r--src/transport/plugin_transport_tcp.c372
-rw-r--r--src/transport/plugin_transport_template.c38
4 files changed, 508 insertions, 493 deletions
diff --git a/src/transport/gnunet-service-transport.c b/src/transport/gnunet-service-transport.c
index 079dc1703..c34efec6c 100644
--- a/src/transport/gnunet-service-transport.c
+++ b/src/transport/gnunet-service-transport.c
@@ -437,70 +437,6 @@ struct TransportClient
437 437
438 438
439/** 439/**
440 * Message used to ask a peer to validate receipt (to check an address
441 * from a HELLO). Followed by the address used. Note that the
442 * recipients response does not affirm that he has this address,
443 * only that he got the challenge message.
444 */
445struct ValidationChallengeMessage
446{
447
448 /**
449 * Type will be GNUNET_MESSAGE_TYPE_TRANSPORT_PING
450 */
451 struct GNUNET_MessageHeader header;
452
453 /**
454 * What are we signing and why?
455 */
456 struct GNUNET_CRYPTO_RsaSignaturePurpose purpose;
457
458 /**
459 * Random challenge number (in network byte order).
460 */
461 uint32_t challenge GNUNET_PACKED;
462
463 /**
464 * Who is the intended recipient?
465 */
466 struct GNUNET_PeerIdentity target;
467};
468
469
470/**
471 * Message used to validate a HELLO. If this was
472 * the right recipient, the response is a signature
473 * of the original validation request. The
474 * challenge is included in the confirmation to make
475 * matching of replies to requests possible.
476 */
477struct ValidationChallengeResponse
478{
479
480 /**
481 * Type will be GNUNET_MESSAGE_TYPE_TRANSPORT_PONG
482 */
483 struct GNUNET_MessageHeader header;
484
485 /**
486 * Random challenge number (in network byte order).
487 */
488 uint32_t challenge GNUNET_PACKED;
489
490 /**
491 * Who signed this message?
492 */
493 struct GNUNET_PeerIdentity sender;
494
495 /**
496 * Signature.
497 */
498 struct GNUNET_CRYPTO_RsaSignature signature;
499
500};
501
502
503/**
504 * For each HELLO, we may have to validate multiple addresses; 440 * For each HELLO, we may have to validate multiple addresses;
505 * each address gets its own request entry. 441 * each address gets its own request entry.
506 */ 442 */
@@ -512,12 +448,6 @@ struct ValidationAddress
512 struct ValidationAddress *next; 448 struct ValidationAddress *next;
513 449
514 /** 450 /**
515 * Our challenge message. Points to after this
516 * struct, so this field should not be freed.
517 */
518 struct ValidationChallengeMessage *msg;
519
520 /**
521 * Name of the transport. 451 * Name of the transport.
522 */ 452 */
523 char *transport_name; 453 char *transport_name;
@@ -533,6 +463,11 @@ struct ValidationAddress
533 size_t addr_len; 463 size_t addr_len;
534 464
535 /** 465 /**
466 * Challenge number we used.
467 */
468 uint32_t challenge;
469
470 /**
536 * Set to GNUNET_YES if the challenge was met, 471 * Set to GNUNET_YES if the challenge was met,
537 * GNUNET_SYSERR if we know it failed, GNUNET_NO 472 * GNUNET_SYSERR if we know it failed, GNUNET_NO
538 * if we are waiting on a response. 473 * if we are waiting on a response.
@@ -940,115 +875,6 @@ transmit_send_continuation (void *cls,
940} 875}
941 876
942 877
943
944
945/**
946 * We could not use an existing (or validated) connection to
947 * talk to a peer. Try addresses that have not yet been
948 * validated.
949 *
950 * @param n neighbour we want to communicate with
951 * @return plugin ready to talk, or NULL if none is available
952 */
953static struct ReadyList *
954try_unvalidated_addresses (struct NeighbourList *n)
955{
956 struct ValidationList *vl;
957 struct ValidationAddress *va;
958 struct GNUNET_PeerIdentity id;
959 struct GNUNET_TIME_Absolute now;
960 unsigned int total;
961 unsigned int cnt;
962 struct ReadyList *rl;
963 struct TransportPlugin *plugin;
964
965#if DEBUG_TRANSPORT
966 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
967 "Trying to connect to `%4s' using unvalidated addresses\n",
968 GNUNET_i2s (&n->id));
969#endif
970 /* NOTE: this function needs to not only identify the
971 plugin but also setup "plugin_handle", binding it to the
972 right address using the plugin's "send_to" API */
973 now = GNUNET_TIME_absolute_get ();
974 vl = pending_validations;
975 while (vl != NULL)
976 {
977 GNUNET_CRYPTO_hash (&vl->publicKey,
978 sizeof (struct
979 GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
980 &id.hashPubKey);
981 if (0 == memcmp (&id, &n->id, sizeof (struct GNUNET_PeerIdentity)))
982 break;
983 vl = vl->next;
984 }
985 if (vl == NULL)
986 {
987#if DEBUG_TRANSPORT
988 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
989 "No unvalidated address found for peer `%4s'\n",
990 GNUNET_i2s (&n->id));
991#endif
992 return NULL;
993 }
994 total = 0;
995 cnt = 0;
996 va = vl->addresses;
997 while (va != NULL)
998 {
999 cnt++;
1000 if (va->expiration.value > now.value)
1001 total++;
1002 va = va->next;
1003 }
1004 if (total == 0)
1005 {
1006#if DEBUG_TRANSPORT
1007 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1008 "All %u unvalidated addresses for peer have expired\n",
1009 cnt);
1010#endif
1011 return NULL;
1012 }
1013 total = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, total);
1014 for (va = vl->addresses; va != NULL; va = va->next)
1015 {
1016 if (va->expiration.value <= now.value)
1017 continue;
1018 if (total > 0)
1019 {
1020 total--;
1021 continue;
1022 }
1023#if DEBUG_TRANSPORT
1024 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
1025 "Trying unvalidated address of `%s' transport\n",
1026 va->transport_name);
1027#endif
1028 plugin = find_transport (va->transport_name);
1029 if (plugin == NULL)
1030 {
1031 GNUNET_break (0);
1032 break;
1033 }
1034 rl = GNUNET_malloc (sizeof (struct ReadyList));
1035 rl->next = n->plugins;
1036 n->plugins = rl;
1037 rl->plugin = plugin;
1038 rl->plugin_handle = plugin->api->send_to (plugin->api->cls,
1039 &n->id,
1040 0,
1041 NULL,
1042 NULL,
1043 GNUNET_TIME_UNIT_ZERO,
1044 &va->msg[1], va->addr_len);
1045 rl->transmit_ready = GNUNET_YES;
1046 return rl;
1047 }
1048 return NULL;
1049}
1050
1051
1052/** 878/**
1053 * Check the ready list for the given neighbour and 879 * Check the ready list for the given neighbour and
1054 * if a plugin is ready for transmission (and if we 880 * if a plugin is ready for transmission (and if we
@@ -1094,8 +920,6 @@ try_transmission_to_peer (struct NeighbourList *neighbour)
1094 pos = pos->next; 920 pos = pos->next;
1095 } 921 }
1096 if (rl == NULL) 922 if (rl == NULL)
1097 rl = try_unvalidated_addresses (neighbour);
1098 if (rl == NULL)
1099 { 923 {
1100#if DEBUG_TRANSPORT 924#if DEBUG_TRANSPORT
1101 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 925 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
@@ -1568,7 +1392,7 @@ list_validated_addresses (void *cls, size_t max, void *buf)
1568 return 0; 1392 return 0;
1569 ret = GNUNET_HELLO_add_address ((*va)->transport_name, 1393 ret = GNUNET_HELLO_add_address ((*va)->transport_name,
1570 (*va)->expiration, 1394 (*va)->expiration,
1571 &(*va)->msg[1], (*va)->addr_len, buf, max); 1395 &(*va)[1], (*va)->addr_len, buf, max);
1572 *va = (*va)->next; 1396 *va = (*va)->next;
1573 return ret; 1397 return ret;
1574} 1398}
@@ -1648,6 +1472,101 @@ cleanup_validation (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1648} 1472}
1649 1473
1650 1474
1475
1476
1477/**
1478 * Function that will be called if we receive a validation
1479 * of an address challenge that we transmitted to another
1480 * peer. Note that the validation should only be considered
1481 * acceptable if the challenge matches AND if the sender
1482 * address is at least a plausible address for this peer
1483 * (otherwise we may be seeing a MiM attack).
1484 *
1485 * @param cls closure
1486 * @param name name of the transport that generated the address
1487 * @param peer who responded to our challenge
1488 * @param challenge the challenge number we presumably used
1489 * @param sender_addr string describing our sender address (as observed
1490 * by the other peer in human-readable format)
1491 */
1492static void
1493plugin_env_notify_validation (void *cls,
1494 const char *name,
1495 const struct GNUNET_PeerIdentity *peer,
1496 uint32_t challenge,
1497 const char *sender_addr)
1498{
1499 int all_done;
1500 int matched;
1501 struct ValidationList *pos;
1502 struct ValidationAddress *va;
1503 struct GNUNET_PeerIdentity id;
1504
1505 pos = pending_validations;
1506 while (pos != NULL)
1507 {
1508 GNUNET_CRYPTO_hash (&pos->publicKey,
1509 sizeof (struct
1510 GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
1511 &id.hashPubKey);
1512 if (0 ==
1513 memcmp (peer, &id, sizeof (struct GNUNET_PeerIdentity)))
1514 break;
1515 pos = pos->next;
1516 }
1517 if (pos == NULL)
1518 {
1519 /* TODO: call statistics (unmatched PONG) */
1520 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1521 _
1522 ("Received validation response but have no record of a matching validation request. Ignoring.\n"));
1523 return;
1524 }
1525 all_done = GNUNET_YES;
1526 matched = GNUNET_NO;
1527 va = pos->addresses;
1528 while (va != NULL)
1529 {
1530 if (va->challenge == challenge)
1531 {
1532#if DEBUG_TRANSPORT
1533 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1534 "Confirmed validity of peer address.\n");
1535#endif
1536 GNUNET_log (GNUNET_ERROR_TYPE_INFO | GNUNET_ERROR_TYPE_BULK,
1537 _("Another peer saw us using the address `%s' via `%s'. If this is not plausible, this address should be listed in the configuration as implausible to avoid MiM attacks.\n"),
1538 sender_addr,
1539 name);
1540 va->ok = GNUNET_YES;
1541 va->expiration =
1542 GNUNET_TIME_relative_to_absolute (HELLO_ADDRESS_EXPIRATION);
1543 matched = GNUNET_YES;
1544 }
1545 if (va->ok != GNUNET_YES)
1546 all_done = GNUNET_NO;
1547 va = va->next;
1548 }
1549 if (GNUNET_NO == matched)
1550 {
1551 /* TODO: call statistics (unmatched PONG) */
1552 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1553 _
1554 ("Received `%s' message but have no record of a matching `%s' message. Ignoring.\n"),
1555 "PONG", "PING");
1556 }
1557 if (GNUNET_YES == all_done)
1558 {
1559 pos->timeout.value = 0;
1560 GNUNET_SCHEDULER_add_delayed (sched,
1561 GNUNET_NO,
1562 GNUNET_SCHEDULER_PRIORITY_IDLE,
1563 GNUNET_SCHEDULER_NO_PREREQUISITE_TASK,
1564 GNUNET_TIME_UNIT_ZERO,
1565 &cleanup_validation, NULL);
1566 }
1567}
1568
1569
1651struct CheckHelloValidatedContext 1570struct CheckHelloValidatedContext
1652{ 1571{
1653 /** 1572 /**
@@ -1681,7 +1600,6 @@ run_validation (void *cls,
1681 struct ValidationList *e = cls; 1600 struct ValidationList *e = cls;
1682 struct TransportPlugin *tp; 1601 struct TransportPlugin *tp;
1683 struct ValidationAddress *va; 1602 struct ValidationAddress *va;
1684 struct ValidationChallengeMessage *vcm;
1685 struct GNUNET_PeerIdentity id; 1603 struct GNUNET_PeerIdentity id;
1686 1604
1687 tp = find_transport (tname); 1605 tp = find_transport (tname);
@@ -1704,25 +1622,14 @@ run_validation (void *cls,
1704 tname, 1622 tname,
1705 GNUNET_i2s(&id)); 1623 GNUNET_i2s(&id));
1706 1624
1707 va = GNUNET_malloc (sizeof (struct ValidationAddress) + 1625 va = GNUNET_malloc (sizeof (struct ValidationAddress) + addrlen);
1708 sizeof (struct ValidationChallengeMessage) + addrlen);
1709 va->next = e->addresses; 1626 va->next = e->addresses;
1710 e->addresses = va; 1627 e->addresses = va;
1711 vcm = (struct ValidationChallengeMessage *) &va[1];
1712 va->msg = vcm;
1713 va->transport_name = GNUNET_strdup (tname); 1628 va->transport_name = GNUNET_strdup (tname);
1714 va->addr_len = addrlen; 1629 va->addr_len = addrlen;
1715 vcm->header.size = 1630 va->challenge = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
1716 htons (sizeof (struct ValidationChallengeMessage) + addrlen); 1631 (unsigned int) -1);
1717 vcm->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_PING); 1632 memcpy (&va[1], addr, addrlen);
1718 vcm->purpose.size =
1719 htonl (sizeof (struct ValidationChallengeMessage) + addrlen -
1720 sizeof (struct GNUNET_MessageHeader));
1721 vcm->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_TRANSPORT_HELLO);
1722 vcm->challenge = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
1723 (unsigned int) -1);
1724 vcm->target = id;
1725 memcpy (&vcm[1], addr, addrlen);
1726 return GNUNET_OK; 1633 return GNUNET_OK;
1727} 1634}
1728 1635
@@ -1735,7 +1642,8 @@ run_validation (void *cls,
1735static void 1642static void
1736check_hello_validated (void *cls, 1643check_hello_validated (void *cls,
1737 const struct GNUNET_PeerIdentity *peer, 1644 const struct GNUNET_PeerIdentity *peer,
1738 const struct GNUNET_HELLO_Message *h, uint32_t trust) 1645 const struct GNUNET_HELLO_Message *h,
1646 uint32_t trust)
1739{ 1647{
1740 struct CheckHelloValidatedContext *chvc = cls; 1648 struct CheckHelloValidatedContext *chvc = cls;
1741 struct ValidationAddress *va; 1649 struct ValidationAddress *va;
@@ -1776,20 +1684,19 @@ check_hello_validated (void *cls,
1776 { 1684 {
1777#if DEBUG_TRANSPORT 1685#if DEBUG_TRANSPORT
1778 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1686 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1779 "Establishing `%s' connection to validate `%s' of `%4s' (sending our `%s')\n", 1687 "Establishing `%s' connection to validate `%s' of `%4s'\n",
1780 va->transport_name, 1688 va->transport_name,
1781 "HELLO", GNUNET_i2s (&va->msg->target), "HELLO"); 1689 "HELLO", GNUNET_i2s (peer));
1782#endif 1690#endif
1783 tp = find_transport (va->transport_name); 1691 tp = find_transport (va->transport_name);
1784 GNUNET_assert (tp != NULL); 1692 GNUNET_assert (tp != NULL);
1785 if (NULL == 1693 if (GNUNET_OK !=
1786 tp->api->send_to (tp->api->cls, 1694 tp->api->validate (tp->api->cls,
1787 &va->msg->target, 1695 peer,
1788 0, 1696 va->challenge,
1789 (const struct GNUNET_MessageHeader *) our_hello, 1697 HELLO_VERIFICATION_TIMEOUT,
1790 &va->msg->header, 1698 &va[1],
1791 HELLO_VERIFICATION_TIMEOUT, 1699 va->addr_len))
1792 &va->msg[1], va->addr_len))
1793 va->ok = GNUNET_SYSERR; 1700 va->ok = GNUNET_SYSERR;
1794 va = va->next; 1701 va = va->next;
1795 } 1702 }
@@ -1885,186 +1792,6 @@ process_hello (struct TransportPlugin *plugin,
1885} 1792}
1886 1793
1887 1794
1888/**
1889 * Handle PING-message. If the plugin that gave us the message is
1890 * able to queue the PONG immediately, we only queue one PONG.
1891 * Otherwise we send at most TWO PONG messages, one via an unconfirmed
1892 * transport and one via a confirmed transport. Both addresses are
1893 * selected randomly among those available.
1894 *
1895 * @param plugin plugin that gave us the message
1896 * @param sender claimed sender of the PING
1897 * @param plugin_context context that might be used to send response
1898 * @param message the actual message
1899 */
1900static void
1901process_ping (struct TransportPlugin *plugin,
1902 const struct GNUNET_PeerIdentity *sender,
1903 void *plugin_context,
1904 const struct GNUNET_MessageHeader *message)
1905{
1906 const struct ValidationChallengeMessage *vcm;
1907 struct ValidationChallengeResponse vcr;
1908 uint16_t msize;
1909 struct NeighbourList *n;
1910
1911#if DEBUG_TRANSPORT
1912 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
1913 "Processing PING\n");
1914#endif
1915 msize = ntohs (message->size);
1916 if (msize < sizeof (struct ValidationChallengeMessage))
1917 {
1918 GNUNET_break_op (0);
1919 return;
1920 }
1921 vcm = (const struct ValidationChallengeMessage *) message;
1922 if (0 != memcmp (&vcm->target,
1923 &my_identity, sizeof (struct GNUNET_PeerIdentity)))
1924 {
1925 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1926 _("Received `%s' message not destined for me!\n"), "PING");
1927 /* TODO: call statistics */
1928 return;
1929 }
1930 if ((ntohl (vcm->purpose.size) !=
1931 msize - sizeof (struct GNUNET_MessageHeader))
1932 || (ntohl (vcm->purpose.purpose) !=
1933 GNUNET_SIGNATURE_PURPOSE_TRANSPORT_HELLO))
1934 {
1935 GNUNET_break_op (0);
1936 return;
1937 }
1938 msize -= sizeof (struct ValidationChallengeMessage);
1939 if (GNUNET_OK !=
1940 plugin->api->address_suggested (plugin->api->cls, &vcm[1], msize))
1941 {
1942 GNUNET_break_op (0);
1943 return;
1944 }
1945 vcr.header.size = htons (sizeof (struct ValidationChallengeResponse));
1946 vcr.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_PONG);
1947 vcr.challenge = vcm->challenge;
1948 vcr.sender = my_identity;
1949 GNUNET_assert (GNUNET_OK ==
1950 GNUNET_CRYPTO_rsa_sign (my_private_key,
1951 &vcm->purpose, &vcr.signature));
1952#if EXTRA_CHECKS
1953 GNUNET_assert (GNUNET_OK ==
1954 GNUNET_CRYPTO_rsa_verify
1955 (GNUNET_SIGNATURE_PURPOSE_TRANSPORT_HELLO, &vcm->purpose,
1956 &vcr.signature, &my_public_key));
1957#endif
1958#if DEBUG_TRANSPORT
1959 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
1960 "Trying to transmit PONG using inbound connection\n");
1961#endif
1962 n = find_neighbour (sender);
1963 if (n == NULL)
1964 {
1965 GNUNET_break (0);
1966 return;
1967 }
1968 transmit_to_peer (NULL, 0, &vcr.header, GNUNET_YES, n);
1969}
1970
1971
1972/**
1973 * Handle PONG-message.
1974 *
1975 * @param message the actual message
1976 */
1977static void
1978process_pong (struct TransportPlugin *plugin,
1979 const struct GNUNET_MessageHeader *message)
1980{
1981 const struct ValidationChallengeResponse *vcr;
1982 struct ValidationList *pos;
1983 struct GNUNET_PeerIdentity peer;
1984 struct ValidationAddress *va;
1985 int all_done;
1986 int matched;
1987
1988#if DEBUG_TRANSPORT
1989 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
1990 "Processing PONG\n");
1991#endif
1992 vcr = (const struct ValidationChallengeResponse *) message;
1993 pos = pending_validations;
1994 while (pos != NULL)
1995 {
1996 GNUNET_CRYPTO_hash (&pos->publicKey,
1997 sizeof (struct
1998 GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
1999 &peer.hashPubKey);
2000 if (0 ==
2001 memcmp (&peer, &vcr->sender, sizeof (struct GNUNET_PeerIdentity)))
2002 break;
2003 pos = pos->next;
2004 }
2005 if (pos == NULL)
2006 {
2007 /* TODO: call statistics (unmatched PONG) */
2008 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
2009 _
2010 ("Received `%s' message but have no record of a matching `%s' message. Ignoring.\n"),
2011 "PONG", "PING");
2012 return;
2013 }
2014 all_done = GNUNET_YES;
2015 matched = GNUNET_NO;
2016 va = pos->addresses;
2017 while (va != NULL)
2018 {
2019 if (va->msg->challenge == vcr->challenge)
2020 {
2021 if (GNUNET_OK !=
2022 GNUNET_CRYPTO_rsa_verify
2023 (GNUNET_SIGNATURE_PURPOSE_TRANSPORT_HELLO, &va->msg->purpose,
2024 &vcr->signature, &pos->publicKey))
2025 {
2026 /* this could rarely happen if we used the same
2027 challenge number for the peer for two different
2028 transports / addresses, but the likelihood is
2029 very small... */
2030 GNUNET_break_op (0);
2031 }
2032 else
2033 {
2034#if DEBUG_TRANSPORT
2035 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2036 "Confirmed validity of peer address.\n");
2037#endif
2038 va->ok = GNUNET_YES;
2039 va->expiration =
2040 GNUNET_TIME_relative_to_absolute (HELLO_ADDRESS_EXPIRATION);
2041 matched = GNUNET_YES;
2042 }
2043 }
2044 if (va->ok != GNUNET_YES)
2045 all_done = GNUNET_NO;
2046 va = va->next;
2047 }
2048 if (GNUNET_NO == matched)
2049 {
2050 /* TODO: call statistics (unmatched PONG) */
2051 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
2052 _
2053 ("Received `%s' message but have no record of a matching `%s' message. Ignoring.\n"),
2054 "PONG", "PING");
2055 }
2056 if (GNUNET_YES == all_done)
2057 {
2058 pos->timeout.value = 0;
2059 GNUNET_SCHEDULER_add_delayed (sched,
2060 GNUNET_NO,
2061 GNUNET_SCHEDULER_PRIORITY_IDLE,
2062 GNUNET_SCHEDULER_NO_PREREQUISITE_TASK,
2063 GNUNET_TIME_UNIT_ZERO,
2064 &cleanup_validation, NULL);
2065 }
2066}
2067
2068 1795
2069/** 1796/**
2070 * The peer specified by the given neighbour has timed-out. Update 1797 * The peer specified by the given neighbour has timed-out. Update
@@ -2342,12 +2069,6 @@ plugin_env_receive (void *cls,
2342#endif 2069#endif
2343 transmit_to_peer (NULL, 0, &ack, GNUNET_YES, n); 2070 transmit_to_peer (NULL, 0, &ack, GNUNET_YES, n);
2344 break; 2071 break;
2345 case GNUNET_MESSAGE_TYPE_TRANSPORT_PING:
2346 process_ping (plugin, peer, plugin_context, message);
2347 break;
2348 case GNUNET_MESSAGE_TYPE_TRANSPORT_PONG:
2349 process_pong (plugin, message);
2350 break;
2351 case GNUNET_MESSAGE_TYPE_TRANSPORT_ACK: 2072 case GNUNET_MESSAGE_TYPE_TRANSPORT_ACK:
2352 n->saw_ack = GNUNET_YES; 2073 n->saw_ack = GNUNET_YES;
2353 /* intentional fall-through! */ 2074 /* intentional fall-through! */
@@ -2639,10 +2360,13 @@ create_environment (struct TransportPlugin *plug)
2639 plug->env.cfg = cfg; 2360 plug->env.cfg = cfg;
2640 plug->env.sched = sched; 2361 plug->env.sched = sched;
2641 plug->env.my_public_key = &my_public_key; 2362 plug->env.my_public_key = &my_public_key;
2363 plug->env.my_private_key = my_private_key;
2364 plug->env.my_identity = &my_identity;
2642 plug->env.cls = plug; 2365 plug->env.cls = plug;
2643 plug->env.receive = &plugin_env_receive; 2366 plug->env.receive = &plugin_env_receive;
2644 plug->env.lookup = &plugin_env_lookup_address; 2367 plug->env.lookup = &plugin_env_lookup_address;
2645 plug->env.notify_address = &plugin_env_notify_address; 2368 plug->env.notify_address = &plugin_env_notify_address;
2369 plug->env.notify_validation = &plugin_env_notify_validation;
2646 plug->env.default_quota_in = (GNUNET_CONSTANTS_DEFAULT_BPM_IN_OUT + 59999) / (60 * 1000); 2370 plug->env.default_quota_in = (GNUNET_CONSTANTS_DEFAULT_BPM_IN_OUT + 59999) / (60 * 1000);
2647 plug->env.max_connections = max_connect_per_transport; 2371 plug->env.max_connections = max_connect_per_transport;
2648} 2372}
diff --git a/src/transport/plugin_transport.h b/src/transport/plugin_transport.h
index e0f83880a..10fad4886 100644
--- a/src/transport/plugin_transport.h
+++ b/src/transport/plugin_transport.h
@@ -91,6 +91,29 @@ typedef struct ReadyList *
91 91
92 92
93/** 93/**
94 * Function that will be called if we receive a validation
95 * of an address challenge that we transmitted to another
96 * peer. Note that the validation should only be considered
97 * acceptable if the challenge matches AND if the sender
98 * address is at least a plausible address for this peer
99 * (otherwise we may be seeing a MiM attack).
100 *
101 * @param cls closure
102 * @param name name of the transport that generated the address
103 * @param peer who responded to our challenge
104 * @param challenge the challenge number we presumably used
105 * @param sender_addr string describing our sender address (as observed
106 * by the other peer in human-readable format)
107 */
108typedef void (*GNUNET_TRANSPORT_ValidationNotification) (void *cls,
109 const char *name,
110 const struct GNUNET_PeerIdentity *peer,
111 uint32_t challenge,
112 const char *sender_addr);
113
114
115
116/**
94 * Function that will be called for each address the transport 117 * Function that will be called for each address the transport
95 * is aware that it might be reachable under. 118 * is aware that it might be reachable under.
96 * 119 *
@@ -167,6 +190,16 @@ struct GNUNET_TRANSPORT_PluginEnvironment
167 struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *my_public_key; 190 struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *my_public_key;
168 191
169 /** 192 /**
193 * Our private key.
194 */
195 struct GNUNET_CRYPTO_RsaPrivateKey *my_private_key;
196
197 /**
198 * Identity of this peer.
199 */
200 const struct GNUNET_PeerIdentity *my_identity;
201
202 /**
170 * Closure for the various callbacks. 203 * Closure for the various callbacks.
171 */ 204 */
172 void *cls; 205 void *cls;
@@ -190,6 +223,14 @@ struct GNUNET_TRANSPORT_PluginEnvironment
190 GNUNET_TRANSPORT_AddressNotification notify_address; 223 GNUNET_TRANSPORT_AddressNotification notify_address;
191 224
192 /** 225 /**
226 * Function that must be called by each plugin to notify the
227 * transport service about a successful validation of an
228 * address of another peer (or at least likely successful
229 * validation).
230 */
231 GNUNET_TRANSPORT_ValidationNotification notify_validation;
232
233 /**
193 * What is the default quota (in terms of incoming bytes per 234 * What is the default quota (in terms of incoming bytes per
194 * ms) for new connections? 235 * ms) for new connections?
195 */ 236 */
@@ -206,34 +247,28 @@ struct GNUNET_TRANSPORT_PluginEnvironment
206 247
207 248
208/** 249/**
209 * Function that can be used by the transport service to transmit 250 * Function that can be used by the transport service to validate
210 * a message using the plugin using a fresh connection (even if 251 * the address of another peer. Even if
211 * we already have a connection to this peer, this function is 252 * we already have a connection to this peer, this function is
212 * required to establish a new one). 253 * required to establish a new one.
213 * 254 *
214 * @param cls closure 255 * @param cls closure
215 * @param target who should receive this message 256 * @param target who should receive this message
216 * @param priority how important is the message 257 * @param challenge challenge code to use
217 * @param msg1 first message to transmit
218 * @param msg2 second message to transmit (can be NULL)
219 * @param timeout how long should we try to transmit these? 258 * @param timeout how long should we try to transmit these?
220 * @param addrlen length of the address 259 * @param addrlen length of the address
221 * @param addr the address 260 * @param addr the address
222 * @return session instance if the transmission has been scheduled 261 * @return GNUNET_OK on success, GNUNET_SYSERR if the address
223 * NULL if the address format is invalid 262 * format is invalid
224 */ 263 */
225typedef void * 264typedef int
226 (*GNUNET_TRANSPORT_TransmitToAddressFunction) (void *cls, 265 (*GNUNET_TRANSPORT_ValidationFunction) (void *cls,
227 const struct 266 const struct
228 GNUNET_PeerIdentity * target, 267 GNUNET_PeerIdentity * target,
229 unsigned int priority, 268 uint32_t challenge,
230 const struct 269 struct GNUNET_TIME_Relative
231 GNUNET_MessageHeader * msg1, 270 timeout, const void *addr,
232 const struct 271 size_t addrlen);
233 GNUNET_MessageHeader * msg2,
234 struct GNUNET_TIME_Relative
235 timeout, const void *addr,
236 size_t addrlen);
237 272
238/** 273/**
239 * Function called by the GNUNET_TRANSPORT_TransmitFunction 274 * Function called by the GNUNET_TRANSPORT_TransmitFunction
@@ -415,7 +450,7 @@ struct GNUNET_TRANSPORT_PluginFunctions
415 * peer using the specified address. Used to validate 450 * peer using the specified address. Used to validate
416 * HELLOs. 451 * HELLOs.
417 */ 452 */
418 GNUNET_TRANSPORT_TransmitToAddressFunction send_to; 453 GNUNET_TRANSPORT_ValidationFunction validate;
419 454
420 /** 455 /**
421 * Function that the transport service will use to transmit data to 456 * Function that the transport service will use to transmit data to
diff --git a/src/transport/plugin_transport_tcp.c b/src/transport/plugin_transport_tcp.c
index 2fc707196..9a2a54890 100644
--- a/src/transport/plugin_transport_tcp.c
+++ b/src/transport/plugin_transport_tcp.c
@@ -33,6 +33,7 @@
33#include "gnunet_resolver_service.h" 33#include "gnunet_resolver_service.h"
34#include "gnunet_server_lib.h" 34#include "gnunet_server_lib.h"
35#include "gnunet_service_lib.h" 35#include "gnunet_service_lib.h"
36#include "gnunet_signatures.h"
36#include "gnunet_statistics_service.h" 37#include "gnunet_statistics_service.h"
37#include "gnunet_transport_service.h" 38#include "gnunet_transport_service.h"
38#include "plugin_transport.h" 39#include "plugin_transport.h"
@@ -62,6 +63,84 @@
62 */ 63 */
63#define ACK_LOG_SIZE 32 64#define ACK_LOG_SIZE 32
64 65
66
67
68/**
69 * Message used to ask a peer to validate receipt (to check an address
70 * from a HELLO). Followed by the address used. Note that the
71 * recipients response does not affirm that he has this address,
72 * only that he got the challenge message.
73 */
74struct ValidationChallengeMessage
75{
76
77 /**
78 * Type will be GNUNET_MESSAGE_TYPE_TRANSPORT_TCP_PING
79 */
80 struct GNUNET_MessageHeader header;
81
82 /**
83 * Random challenge number (in network byte order).
84 */
85 uint32_t challenge GNUNET_PACKED;
86
87 /**
88 * Who is the intended recipient?
89 */
90 struct GNUNET_PeerIdentity target;
91
92};
93
94
95/**
96 * Message used to validate a HELLO. The challenge is included in the
97 * confirmation to make matching of replies to requests possible. The
98 * signature signs the original challenge number, our public key, the
99 * sender's address (so that the sender can check that the address we
100 * saw is plausible for him and possibly detect a MiM attack) and a
101 * timestamp (to limit replay).<p>
102 *
103 * This message is followed by the address of the
104 * client that we are observing (which is part of what
105 * is being signed).
106 */
107struct ValidationChallengeResponse
108{
109
110 /**
111 * Type will be GNUNET_MESSAGE_TYPE_TRANSPORT_TCP_PONG
112 */
113 struct GNUNET_MessageHeader header;
114
115 /**
116 * For padding, always zero.
117 */
118 uint32_t reserved GNUNET_PACKED;
119
120 /**
121 * Signature.
122 */
123 struct GNUNET_CRYPTO_RsaSignature signature;
124
125 /**
126 * What are we signing and why?
127 */
128 struct GNUNET_CRYPTO_RsaSignaturePurpose purpose;
129
130 /**
131 * Random challenge number (in network byte order).
132 */
133 uint32_t challenge GNUNET_PACKED;
134
135 /**
136 * Who signed this message?
137 */
138 struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded signer;
139
140};
141
142
143
65/** 144/**
66 * Initial handshake message for a session. This header 145 * Initial handshake message for a session. This header
67 * is followed by the address that the other peer used to 146 * is followed by the address that the other peer used to
@@ -625,35 +704,30 @@ process_pending_messages (struct Session *session)
625 704
626 705
627/** 706/**
628 * Function that can be used by the transport service to transmit 707 * Function that can be used by the transport service to validate that
629 * a message using the plugin using a fresh connection (even if 708 * another peer is reachable at a particular address (even if we
630 * we already have a connection to this peer, this function is 709 * already have a connection to this peer, this function is required
631 * required to establish a new one). 710 * to establish a new one).
632 * 711 *
633 * @param cls closure 712 * @param cls closure
634 * @param target who should receive this message 713 * @param target who should receive this message
635 * @param priority how important is the message 714 * @param challenge challenge code to use
636 * @param msg1 first message to transmit
637 * @param msg2 second message to transmit (can be NULL)
638 * @param timeout how long should we try to transmit these?
639 * @param addrlen length of the address 715 * @param addrlen length of the address
640 * @param addr the address 716 * @param addr the address
641 * @return session if the transmission has been scheduled 717 * @param timeout how long should we try to transmit these?
642 * NULL if the address format is invalid 718 * @return GNUNET_OK if the transmission has been scheduled
643 */ 719 */
644static void * 720static int
645tcp_plugin_send_to (void *cls, 721tcp_plugin_validate (void *cls,
646 const struct GNUNET_PeerIdentity *target, 722 const struct GNUNET_PeerIdentity *target,
647 unsigned int priority, 723 uint32_t challenge,
648 const struct GNUNET_MessageHeader *msg1, 724 struct GNUNET_TIME_Relative timeout,
649 const struct GNUNET_MessageHeader *msg2, 725 const void *addr, size_t addrlen)
650 struct GNUNET_TIME_Relative timeout,
651 const void *addr, size_t addrlen)
652{ 726{
653 struct Plugin *plugin = cls; 727 struct Plugin *plugin = cls;
654 struct Session *session; 728 struct Session *session;
655 struct PendingMessage *pl;
656 struct PendingMessage *pm; 729 struct PendingMessage *pm;
730 struct ValidationChallengeMessage *vcm;
657 731
658 session = connect_and_create_session (plugin, target, addr, addrlen); 732 session = connect_and_create_session (plugin, target, addr, addrlen);
659 if (session == NULL) 733 if (session == NULL)
@@ -662,44 +736,24 @@ tcp_plugin_send_to (void *cls,
662 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, 736 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG,
663 "tcp", "Failed to create fresh session.\n"); 737 "tcp", "Failed to create fresh session.\n");
664#endif 738#endif
665 return NULL; 739 return GNUNET_SYSERR;
666 }
667 pl = NULL;
668 if (msg2 != NULL)
669 {
670 pm = GNUNET_malloc (sizeof (struct PendingMessage) +
671 ntohs (msg2->size));
672 pm->msg = (struct GNUNET_MessageHeader *) &pm[1];
673 memcpy (pm->msg, msg2, ntohs (msg2->size));
674 pm->timeout = GNUNET_TIME_relative_to_absolute (timeout);
675 pm->is_welcome = GNUNET_NO;
676 pl = pm;
677 }
678 if (msg1 != NULL)
679 {
680 pm = GNUNET_malloc (sizeof (struct PendingMessage) +
681 ntohs (msg1->size));
682 pm->msg = (struct GNUNET_MessageHeader *) &pm[1];
683 memcpy (pm->msg, msg1, ntohs (msg1->size));
684 pm->timeout = GNUNET_TIME_relative_to_absolute (timeout);
685 pm->is_welcome = GNUNET_NO;
686 pm->next = pl;
687 pl = pm;
688 }
689 /* append */
690 if (session->pending_messages != NULL)
691 {
692 pm = session->pending_messages;
693 while (pm->next != NULL)
694 pm = pm->next;
695 pm->next = pl;
696 }
697 else
698 {
699 session->pending_messages = pl;
700 } 740 }
741 pm = GNUNET_malloc (sizeof (struct PendingMessage) +
742 sizeof (struct ValidationChallengeMessage) + addrlen);
743 pm->msg = (struct GNUNET_MessageHeader *) &pm[1];
744 pm->timeout = GNUNET_TIME_relative_to_absolute (timeout);
745 pm->is_welcome = GNUNET_YES;
746 vcm = (struct ValidationChallengeMessage*) &pm[1];
747 vcm->header.size =
748 htons (sizeof (struct ValidationChallengeMessage) + addrlen);
749 vcm->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_TCP_PING);
750 vcm->challenge = htonl(challenge);
751 vcm->target = *target;
752 memcpy (&vcm[1], addr, addrlen);
753 GNUNET_assert (session->pending_messages == NULL);
754 session->pending_messages = pm;
701 process_pending_messages (session); 755 process_pending_messages (session);
702 return session; 756 return GNUNET_OK;
703} 757}
704 758
705 759
@@ -1346,6 +1400,210 @@ tcp_plugin_address_suggested (void *cls, const void *addr, size_t addrlen)
1346 1400
1347 1401
1348/** 1402/**
1403 * Send a validation challenge response.
1404 */
1405static size_t
1406send_vcr (void *cls,
1407 size_t size,
1408 void *buf)
1409{
1410 struct ValidationChallengeResponse *vcr = cls;
1411 uint16_t msize;
1412
1413 if (NULL == buf)
1414 {
1415 GNUNET_free (vcr);
1416 return 0;
1417 }
1418 msize = ntohs(vcr->header.size);
1419 GNUNET_assert (size >= msize);
1420 memcpy (buf, vcr, msize);
1421 GNUNET_free (vcr);
1422 return msize;
1423}
1424
1425
1426/**
1427 * We've received a PING from this peer via TCP.
1428 * Send back our PONG.
1429 *
1430 * @param cls closure
1431 * @param client identification of the client
1432 * @param message the actual message
1433 */
1434static void
1435handle_tcp_ping (void *cls,
1436 struct GNUNET_SERVER_Client *client,
1437 const struct GNUNET_MessageHeader *message)
1438{
1439 struct Plugin *plugin = cls;
1440 const struct ValidationChallengeMessage *vcm;
1441 struct ValidationChallengeResponse *vcr;
1442 uint16_t msize;
1443 size_t addrlen;
1444 void *addr;
1445
1446#if DEBUG_TRANSPORT
1447 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
1448 "Processing PING\n");
1449#endif
1450 msize = ntohs (message->size);
1451 if (msize < sizeof (struct ValidationChallengeMessage))
1452 {
1453 GNUNET_break_op (0);
1454 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1455 return;
1456 }
1457 vcm = (const struct ValidationChallengeMessage *) message;
1458 if (0 != memcmp (&vcm->target,
1459 plugin->env->my_identity, sizeof (struct GNUNET_PeerIdentity)))
1460 {
1461 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1462 _("Received `%s' message not destined for me!\n"), "PING");
1463 /* TODO: call statistics */
1464 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1465 return;
1466 }
1467 msize -= sizeof (struct ValidationChallengeMessage);
1468 if (GNUNET_OK !=
1469 tcp_plugin_address_suggested (plugin, &vcm[1], msize))
1470 {
1471 GNUNET_break_op (0);
1472 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1473 return;
1474 }
1475 if (GNUNET_OK !=
1476 GNUNET_SERVER_client_get_address (client,
1477 &addr,
1478 &addrlen))
1479 {
1480 GNUNET_break (0);
1481 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1482 return;
1483 }
1484 vcr = GNUNET_malloc (sizeof (struct ValidationChallengeResponse) + addrlen);
1485 vcr->header.size = htons (sizeof (struct ValidationChallengeResponse) + addrlen);
1486 vcr->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_TCP_PONG);
1487 vcr->purpose.size =
1488 htonl (sizeof (struct GNUNET_CRYPTO_RsaSignaturePurpose) +
1489 sizeof (uint32_t) +
1490 sizeof ( struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded) +
1491 addrlen);
1492 vcr->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_TRANSPORT_TCP_PING);
1493 vcr->challenge = vcm->challenge;
1494 vcr->signer = *plugin->env->my_public_key;
1495 memcpy (&vcr[1],
1496 addr,
1497 addrlen);
1498 GNUNET_assert (GNUNET_OK ==
1499 GNUNET_CRYPTO_rsa_sign (plugin->env->my_private_key,
1500 &vcr->purpose,
1501 &vcr->signature));
1502#if EXTRA_CHECKS
1503 GNUNET_assert (GNUNET_OK ==
1504 GNUNET_CRYPTO_rsa_verify
1505 (GNUNET_SIGNATURE_PURPOSE_TRANSPORT_TCP_PING,
1506 &vcr->purpose,
1507 &vcr->signature,
1508 plugin->env->my_public_key));
1509#endif
1510 GNUNET_free (addr);
1511 if (NULL ==
1512 GNUNET_SERVER_notify_transmit_ready (client,
1513 sizeof (struct ValidationChallengeResponse) + addrlen,
1514 GNUNET_TIME_UNIT_SECONDS,
1515 &send_vcr,
1516 vcr))
1517 {
1518 GNUNET_break (0);
1519 GNUNET_free (vcr);
1520 }
1521 /* after a PING, we always close the connection */
1522 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1523}
1524
1525
1526/**
1527 * Handle PING-message. If the plugin that gave us the message is
1528 * able to queue the PONG immediately, we only queue one PONG.
1529 * Otherwise we send at most TWO PONG messages, one via an unconfirmed
1530 * transport and one via a confirmed transport. Both addresses are
1531 * selected randomly among those available.
1532 *
1533 * @param plugin plugin that gave us the message
1534 * @param sender claimed sender of the PING
1535 * @param plugin_context context that might be used to send response
1536 * @param message the actual message
1537 */
1538/**
1539 * We've received a PING from this peer via TCP.
1540 * Send back our PONG.
1541 *
1542 * @param cls closure
1543 * @param client identification of the client
1544 * @param message the actual message
1545 */
1546static void
1547handle_tcp_pong (void *cls,
1548 struct GNUNET_SERVER_Client *client,
1549 const struct GNUNET_MessageHeader *message)
1550{
1551 struct Plugin *plugin = cls;
1552 const struct ValidationChallengeResponse *vcr;
1553 struct GNUNET_PeerIdentity peer;
1554 char *sender_addr;
1555 size_t addrlen;
1556
1557#if DEBUG_TRANSPORT
1558 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
1559 "Processing PONG\n");
1560#endif
1561 if (ntohs(message->size) < sizeof(struct ValidationChallengeResponse))
1562 {
1563 GNUNET_break_op (0);
1564 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1565 return;
1566 }
1567 addrlen = ntohs(message->size) - sizeof(struct ValidationChallengeResponse);
1568 vcr = (const struct ValidationChallengeResponse *) message;
1569 if ( (ntohs(vcr->purpose.size) !=
1570 sizeof (struct GNUNET_CRYPTO_RsaSignaturePurpose) +
1571 sizeof (uint32_t) +
1572 sizeof ( struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded) +
1573 addrlen))
1574 {
1575 GNUNET_break_op (0);
1576 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1577 return;
1578 }
1579 if (GNUNET_OK !=
1580 GNUNET_CRYPTO_rsa_verify
1581 (GNUNET_SIGNATURE_PURPOSE_TRANSPORT_TCP_PING,
1582 &vcr->purpose,
1583 &vcr->signature,
1584 &vcr->signer))
1585 {
1586 GNUNET_break_op (0);
1587 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1588 return;
1589 }
1590 GNUNET_CRYPTO_hash (&vcr->signer,
1591 sizeof( struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
1592 &peer.hashPubKey);
1593 sender_addr = GNUNET_strdup (GNUNET_a2s((const struct sockaddr*) &vcr[1],
1594 addrlen));
1595 plugin->env->notify_validation (plugin->env->cls,
1596 "tcp",
1597 &peer,
1598 ntohs(vcr->challenge),
1599 sender_addr);
1600 GNUNET_free (sender_addr);
1601 /* after a PONG, we always close the connection */
1602 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1603}
1604
1605
1606/**
1349 * We've received a welcome from this peer via TCP. 1607 * We've received a welcome from this peer via TCP.
1350 * Possibly create a fresh client record and send back 1608 * Possibly create a fresh client record and send back
1351 * our welcome. 1609 * our welcome.
@@ -1562,6 +1820,8 @@ handle_tcp_data (void *cls,
1562 * Handlers for the various TCP messages. 1820 * Handlers for the various TCP messages.
1563 */ 1821 */
1564static struct GNUNET_SERVER_MessageHandler my_handlers[] = { 1822static struct GNUNET_SERVER_MessageHandler my_handlers[] = {
1823 {&handle_tcp_ping, NULL, GNUNET_MESSAGE_TYPE_TRANSPORT_TCP_PING, 0},
1824 {&handle_tcp_pong, NULL, GNUNET_MESSAGE_TYPE_TRANSPORT_TCP_PONG, 0},
1565 {&handle_tcp_welcome, NULL, GNUNET_MESSAGE_TYPE_TRANSPORT_TCP_WELCOME, 0}, 1825 {&handle_tcp_welcome, NULL, GNUNET_MESSAGE_TYPE_TRANSPORT_TCP_WELCOME, 0},
1566 {&handle_tcp_data, NULL, GNUNET_MESSAGE_TYPE_TRANSPORT_TCP_DATA, 0}, 1826 {&handle_tcp_data, NULL, GNUNET_MESSAGE_TYPE_TRANSPORT_TCP_DATA, 0},
1567 {NULL, NULL, 0, 0} 1827 {NULL, NULL, 0, 0}
@@ -1728,7 +1988,7 @@ libgnunet_plugin_transport_tcp_init (void *cls)
1728 plugin->statistics = NULL; 1988 plugin->statistics = NULL;
1729 api = GNUNET_malloc (sizeof (struct GNUNET_TRANSPORT_PluginFunctions)); 1989 api = GNUNET_malloc (sizeof (struct GNUNET_TRANSPORT_PluginFunctions));
1730 api->cls = plugin; 1990 api->cls = plugin;
1731 api->send_to = &tcp_plugin_send_to; 1991 api->validate = &tcp_plugin_validate;
1732 api->send = &tcp_plugin_send; 1992 api->send = &tcp_plugin_send;
1733 api->cancel = &tcp_plugin_cancel; 1993 api->cancel = &tcp_plugin_cancel;
1734 api->address_pretty_printer = &tcp_plugin_address_pretty_printer; 1994 api->address_pretty_printer = &tcp_plugin_address_pretty_printer;
diff --git a/src/transport/plugin_transport_template.c b/src/transport/plugin_transport_template.c
index 496e2cf78..bce4bbc52 100644
--- a/src/transport/plugin_transport_template.c
+++ b/src/transport/plugin_transport_template.c
@@ -132,33 +132,29 @@ struct Plugin
132 132
133 133
134/** 134/**
135 * Function that can be used by the transport service to transmit 135 * Function that can be used by the transport service to validate that
136 * a message using the plugin using a fresh connection (even if 136 * another peer is reachable at a particular address (even if we
137 * we already have a connection to this peer, this function is 137 * already have a connection to this peer, this function is required
138 * required to establish a new one). 138 * to establish a new one).
139 * 139 *
140 * @param cls closure 140 * @param cls closure
141 * @param target who should receive this message 141 * @param target who should receive this message
142 * @param priority how important is the message 142 * @param challenge challenge code to use
143 * @param msg1 first message to transmit
144 * @param msg2 second message to transmit (can be NULL)
145 * @param timeout how long until we give up?
146 * @param addr the address
147 * @param addrlen length of the address 143 * @param addrlen length of the address
148 * @return non-null session if the transmission has been scheduled 144 * @param addr the address
149 * NULL if the address format is invalid 145 * @param timeout how long should we try to transmit these?
146 * @return GNUNET_OK if the transmission has been scheduled
150 */ 147 */
151static void * 148static int
152template_plugin_send_to (void *cls, 149template_plugin_validate (void *cls,
153 const struct GNUNET_PeerIdentity *target, 150 const struct GNUNET_PeerIdentity *target,
154 unsigned int priority, 151 uint32_t challenge,
155 const struct GNUNET_MessageHeader *msg1, 152 struct GNUNET_TIME_Relative timeout,
156 const struct GNUNET_MessageHeader *msg2, 153 const void *addr,
157 struct GNUNET_TIME_Relative timeout, 154 size_t addrlen)
158 const void *addr, size_t addrlen)
159{ 155{
160 // FIXME 156 // FIXME
161 return NULL; 157 return GNUNET_SYSERR;
162} 158}
163 159
164 160
@@ -311,7 +307,7 @@ gnunet_plugin_transport_template_init (void *cls)
311 plugin->statistics = NULL; 307 plugin->statistics = NULL;
312 api = GNUNET_malloc (sizeof (struct GNUNET_TRANSPORT_PluginFunctions)); 308 api = GNUNET_malloc (sizeof (struct GNUNET_TRANSPORT_PluginFunctions));
313 api->cls = plugin; 309 api->cls = plugin;
314 api->send_to = &template_plugin_send_to; 310 api->validate = &template_plugin_validate;
315 api->send = &template_plugin_send; 311 api->send = &template_plugin_send;
316 api->cancel = &template_plugin_cancel; 312 api->cancel = &template_plugin_cancel;
317 api->address_pretty_printer = &template_plugin_address_pretty_printer; 313 api->address_pretty_printer = &template_plugin_address_pretty_printer;