aboutsummaryrefslogtreecommitdiff
path: root/src/transport
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2010-11-24 16:17:18 +0000
committerChristian Grothoff <christian@grothoff.org>2010-11-24 16:17:18 +0000
commit048dbb97f03a8467f7d444bf4533abd4cbd89b09 (patch)
treed8dbb4cb7f5e67880280bdf55f0a26981dc9a25b /src/transport
parentc6fe079ca7000f7cd1fe6978d891f4d75b9f44ba (diff)
downloadgnunet-048dbb97f03a8467f7d444bf4533abd4cbd89b09.tar.gz
gnunet-048dbb97f03a8467f7d444bf4533abd4cbd89b09.zip
adding UPnP/PMP library calls/support to TCP transport
Diffstat (limited to 'src/transport')
-rw-r--r--src/transport/Makefile.am1
-rw-r--r--src/transport/gnunet-service-transport.c9
-rw-r--r--src/transport/plugin_transport_tcp.c610
-rw-r--r--src/transport/test_quota_compliance_tcp_peer1.conf6
-rw-r--r--src/transport/test_quota_compliance_tcp_peer2.conf6
-rw-r--r--src/transport/test_transport_api_tcp_nat_peer1.conf1
-rw-r--r--src/transport/test_transport_api_tcp_peer1.conf5
-rw-r--r--src/transport/test_transport_api_tcp_peer2.conf5
8 files changed, 439 insertions, 204 deletions
diff --git a/src/transport/Makefile.am b/src/transport/Makefile.am
index dc1eebfbb..313d94854 100644
--- a/src/transport/Makefile.am
+++ b/src/transport/Makefile.am
@@ -117,6 +117,7 @@ libgnunet_plugin_transport_tcp_la_LIBADD = \
117 $(top_builddir)/src/hello/libgnunethello.la \ 117 $(top_builddir)/src/hello/libgnunethello.la \
118 $(top_builddir)/src/statistics/libgnunetstatistics.la \ 118 $(top_builddir)/src/statistics/libgnunetstatistics.la \
119 $(top_builddir)/src/peerinfo/libgnunetpeerinfo.la \ 119 $(top_builddir)/src/peerinfo/libgnunetpeerinfo.la \
120 $(top_builddir)/src/nat/libgnunetnat.la \
120 $(top_builddir)/src/util/libgnunetutil.la 121 $(top_builddir)/src/util/libgnunetutil.la
121libgnunet_plugin_transport_tcp_la_LDFLAGS = \ 122libgnunet_plugin_transport_tcp_la_LDFLAGS = \
122 $(GN_PLUGIN_LDFLAGS) 123 $(GN_PLUGIN_LDFLAGS)
diff --git a/src/transport/gnunet-service-transport.c b/src/transport/gnunet-service-transport.c
index bd060a561..e2168b970 100644
--- a/src/transport/gnunet-service-transport.c
+++ b/src/transport/gnunet-service-transport.c
@@ -1905,7 +1905,8 @@ expire_address_task (void *cls,
1905 * expired 1905 * expired
1906 */ 1906 */
1907static void 1907static void
1908update_addresses (struct TransportPlugin *plugin, int fresh) 1908update_addresses (struct TransportPlugin *plugin,
1909 int fresh)
1909{ 1910{
1910 static struct GNUNET_TIME_Absolute last_update; 1911 static struct GNUNET_TIME_Absolute last_update;
1911 struct GNUNET_TIME_Relative min_remaining; 1912 struct GNUNET_TIME_Relative min_remaining;
@@ -2181,9 +2182,9 @@ plugin_env_notify_address (void *cls,
2181 while (al != NULL) 2182 while (al != NULL)
2182 { 2183 {
2183 if ((addrlen == al->addrlen) && (0 == memcmp (addr, &al[1], addrlen))) 2184 if ((addrlen == al->addrlen) && (0 == memcmp (addr, &al[1], addrlen)))
2184 { 2185 {
2185 if (al->expires.abs_value < abex.abs_value) 2186 al->expires = abex;
2186 al->expires = abex; 2187 update_addresses (p, GNUNET_NO);
2187 return; 2188 return;
2188 } 2189 }
2189 al = al->next; 2190 al = al->next;
diff --git a/src/transport/plugin_transport_tcp.c b/src/transport/plugin_transport_tcp.c
index 015de3d8a..134bf5040 100644
--- a/src/transport/plugin_transport_tcp.c
+++ b/src/transport/plugin_transport_tcp.c
@@ -26,6 +26,7 @@
26#include "gnunet_hello_lib.h" 26#include "gnunet_hello_lib.h"
27#include "gnunet_connection_lib.h" 27#include "gnunet_connection_lib.h"
28#include "gnunet_container_lib.h" 28#include "gnunet_container_lib.h"
29#include "gnunet_nat_lib.h"
29#include "gnunet_os_lib.h" 30#include "gnunet_os_lib.h"
30#include "gnunet_protocols.h" 31#include "gnunet_protocols.h"
31#include "gnunet_resolver_service.h" 32#include "gnunet_resolver_service.h"
@@ -89,6 +90,17 @@ struct TCP_NAT_ProbeMessage
89 */ 90 */
90struct TCPProbeContext 91struct TCPProbeContext
91{ 92{
93
94 /**
95 * Active probes are kept in a DLL.
96 */
97 struct TCPProbeContext *next;
98
99 /**
100 * Active probes are kept in a DLL.
101 */
102 struct TCPProbeContext *prev;
103
92 /** 104 /**
93 * Probe connection. 105 * Probe connection.
94 */ 106 */
@@ -171,6 +183,27 @@ struct LocalAddrList
171 struct LocalAddrList *prev; 183 struct LocalAddrList *prev;
172 184
173 /** 185 /**
186 * Link to plugin.
187 */
188 struct Plugin *plugin;
189
190 /**
191 * Handle to NAT holes we've tried to punch for this address.
192 */
193 struct GNUNET_NAT_Handle *nat;
194
195 /**
196 * Pointer to a 'struct IPv4/V6TcpAddress' describing our external IP and port
197 * as obtained from the NAT by automatic port mapping.
198 */
199 void *external_nat_address;
200
201 /**
202 * Number of bytes in 'external_nat_address'
203 */
204 size_t ena_size;
205
206 /**
174 * Number of bytes of the address that follow 207 * Number of bytes of the address that follow
175 */ 208 */
176 size_t size; 209 size_t size;
@@ -383,13 +416,15 @@ struct Plugin
383 struct GNUNET_CONTAINER_MultiHashMap *nat_wait_conns; 416 struct GNUNET_CONTAINER_MultiHashMap *nat_wait_conns;
384 417
385 /** 418 /**
386 * The external address given to us by the user. Must be actual 419 * The external address given to us by the user. Used for HELLOs
387 * outside visible address for NAT punching to work. 420 * and address validation.
388 */ 421 */
389 char *external_address; 422 char *external_address;
390 423
391 /** 424 /**
392 * The internal address given to us by the user (or discovered). 425 * The internal address given to us by the user (or discovered).
426 * Used for NAT traversal (ICMP method), but not as a 'validateable'
427 * address in HELLOs.
393 */ 428 */
394 char *internal_address; 429 char *internal_address;
395 430
@@ -409,6 +444,16 @@ struct Plugin
409 struct LocalAddrList *lal_tail; 444 struct LocalAddrList *lal_tail;
410 445
411 /** 446 /**
447 * List of active TCP probes.
448 */
449 struct TCPProbeContext *probe_head;
450
451 /**
452 * List of active TCP probes.
453 */
454 struct TCPProbeContext *probe_tail;
455
456 /**
412 * ID of task used to update our addresses when one expires. 457 * ID of task used to update our addresses when one expires.
413 */ 458 */
414 GNUNET_SCHEDULER_TaskIdentifier address_update_task; 459 GNUNET_SCHEDULER_TaskIdentifier address_update_task;
@@ -435,16 +480,81 @@ struct Plugin
435 int allow_nat; 480 int allow_nat;
436 481
437 /** 482 /**
438 * Should this transport advertise only NAT addresses (port set to 0)? 483 * Are we allowed to try UPnP/PMP for NAT traversal?
439 * If not, all addresses will be duplicated for NAT punching and regular
440 * ports.
441 */ 484 */
442 int only_nat_addresses; 485 int allow_upnp;
443 486
444}; 487};
445 488
446 489
447/** 490/**
491 * Our external IP address/port mapping has changed.
492 *
493 * @param cls closure, the 'struct LocalAddrList'
494 * @param add_remove GNUNET_YES to mean the new public IP address, GNUNET_NO to mean
495 * the previous (now invalid) one
496 * @param addr either the previous or the new public IP address
497 * @param addrlen actual lenght of the address
498 */
499static void
500nat_port_map_callback (void *cls,
501 int add_remove,
502 const struct sockaddr *addr,
503 socklen_t addrlen)
504{
505 struct LocalAddrList *lal = cls;
506 struct Plugin *plugin = lal->plugin;
507 int af;
508 struct IPv4TcpAddress t4;
509 struct IPv6TcpAddress t6;
510 void *arg;
511 uint16_t args;
512
513 /* convert 'addr' to our internal format */
514 af = addr->sa_family;
515 switch (af)
516 {
517 case AF_INET:
518 t4.ipv4_addr = ((struct sockaddr_in *) addr)->sin_addr.s_addr;
519 t6.t6_port = ((struct sockaddr_in *) addr)->sin_port;
520 arg = &t4;
521 args = sizeof (t4);
522 break;
523 case AF_INET6:
524 memcpy (&t6.ipv6_addr,
525 &((struct sockaddr_in6 *) addr)->sin6_addr,
526 sizeof (struct in6_addr));
527 t6.t6_port = ((struct sockaddr_in6 *) addr)->sin6_port;
528 arg = &t6;
529 args = sizeof (t6);
530 break;
531 default:
532 GNUNET_break (0);
533 return;
534 }
535
536 /* modify our published address list */
537 if (GNUNET_YES == add_remove)
538 {
539 plugin->env->notify_address (plugin->env->cls,
540 "tcp",
541 arg, args, GNUNET_TIME_UNIT_FOREVER_REL);
542 GNUNET_free_non_null (lal->external_nat_address);
543 lal->external_nat_address = GNUNET_memdup (arg, args);
544 lal->ena_size = args;
545 }
546 else
547 {
548 plugin->env->notify_address (plugin->env->cls,
549 "tcp",
550 arg, args, GNUNET_TIME_UNIT_ZERO);
551 GNUNET_free_non_null (lal->external_nat_address);
552 lal->ena_size = 0;
553 }
554}
555
556
557/**
448 * Add the given address to the list of 'local' addresses, thereby 558 * Add the given address to the list of 'local' addresses, thereby
449 * making it a 'legal' address for this peer to have. 559 * making it a 'legal' address for this peer to have.
450 * 560 *
@@ -458,6 +568,10 @@ add_to_address_list (struct Plugin *plugin,
458 size_t arg_size) 568 size_t arg_size)
459{ 569{
460 struct LocalAddrList *lal; 570 struct LocalAddrList *lal;
571 struct sockaddr_in v4;
572 struct sockaddr_in6 v6;
573 const struct sockaddr *sa;
574 socklen_t salen;
461 575
462 lal = plugin->lal_head; 576 lal = plugin->lal_head;
463 while (NULL != lal) 577 while (NULL != lal)
@@ -468,11 +582,47 @@ add_to_address_list (struct Plugin *plugin,
468 lal = lal->next; 582 lal = lal->next;
469 } 583 }
470 lal = GNUNET_malloc (sizeof (struct LocalAddrList) + arg_size); 584 lal = GNUNET_malloc (sizeof (struct LocalAddrList) + arg_size);
585 lal->plugin = plugin;
471 lal->size = arg_size; 586 lal->size = arg_size;
472 memcpy (&lal[1], arg, arg_size); 587 memcpy (&lal[1], arg, arg_size);
473 GNUNET_CONTAINER_DLL_insert (plugin->lal_head, 588 GNUNET_CONTAINER_DLL_insert (plugin->lal_head,
474 plugin->lal_tail, 589 plugin->lal_tail,
475 lal); 590 lal);
591 if (plugin->open_port == 0)
592 return; /* we're not listening at all... */
593 if (arg_size == sizeof (struct in_addr))
594 {
595 memset (&v4, 0, sizeof (v4));
596 v4.sin_family = AF_INET;
597 v4.sin_port = htons (plugin->open_port);
598 memcpy (&v4.sin_addr, arg, arg_size);
599#if HAVE_SOCKADDR_IN_SIN_LEN
600 v4.sin_len = sizeof (struct sockaddr_in);
601#endif
602 sa = (const struct sockaddr*) &v4;
603 salen = sizeof (v4);
604 }
605 else if (arg_size == sizeof (struct in6_addr))
606 {
607 memset (&v6, 0, sizeof (v6));
608 v6.sin6_family = AF_INET6;
609 v6.sin6_port = htons (plugin->open_port);
610 memcpy (&v6.sin6_addr, arg, arg_size);
611#if HAVE_SOCKADDR_IN_SIN_LEN
612 v6.sin_len = sizeof (struct sockaddr_in6);
613#endif
614 sa = (const struct sockaddr*) &v6;
615 salen = sizeof (v6);
616 }
617 else
618 {
619 GNUNET_break (0);
620 return;
621 }
622 if (plugin->allow_upnp)
623 lal->nat = GNUNET_NAT_register (sa, salen,
624 &nat_port_map_callback,
625 lal);
476} 626}
477 627
478 628
@@ -504,6 +654,33 @@ check_local_addr (struct Plugin *plugin,
504 654
505 655
506/** 656/**
657 * Check if the given address is in the list of 'mapped' addresses.
658 *
659 * @param plugin the plugin
660 * @param arg the address, either a 'struct IPv4TcpAddress' or a 'struct IPv6TcpAddress'
661 * @param arg_size number of bytes in arg
662 * @return GNUNET_OK if this is one of our IPs, GNUNET_SYSERR if not
663 */
664static int
665check_mapped_addr (struct Plugin *plugin,
666 const void *arg,
667 size_t arg_size)
668{
669 struct LocalAddrList *lal;
670
671 lal = plugin->lal_head;
672 while (NULL != lal)
673 {
674 if ( (lal->ena_size == arg_size) &&
675 (0 == memcmp (lal->external_nat_address, arg, arg_size)) )
676 return GNUNET_OK;
677 lal = lal->next;
678 }
679 return GNUNET_SYSERR;
680}
681
682
683/**
507 * Function called for a quick conversion of the binary address to 684 * Function called for a quick conversion of the binary address to
508 * a numeric address. Note that the caller must not free the 685 * a numeric address. Note that the caller must not free the
509 * address and that the next call to this function is allowed 686 * address and that the next call to this function is allowed
@@ -843,13 +1020,12 @@ disconnect_session (struct Session *session)
843#if DEBUG_TCP 1020#if DEBUG_TCP
844 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, 1021 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG,
845 "tcp", 1022 "tcp",
846 "Disconnecting from `%4s' at %s (session %p).\n", 1023 "Disconnecting from `%4s' at %s.\n",
847 GNUNET_i2s (&session->target), 1024 GNUNET_i2s (&session->target),
848 (session->connect_addr != NULL) ? 1025 (session->connect_addr != NULL) ?
849 tcp_address_to_string (session->plugin, 1026 tcp_address_to_string (session->plugin,
850 session->connect_addr, 1027 session->connect_addr,
851 session->connect_alen) : "*", 1028 session->connect_alen) : "*");
852 session);
853#endif 1029#endif
854 /* remove from session list */ 1030 /* remove from session list */
855 prev = NULL; 1031 prev = NULL;
@@ -968,6 +1144,13 @@ run_gnunet_nat_client (struct Plugin *plugin,
968 char port_as_string[6]; 1144 char port_as_string[6];
969 struct GNUNET_OS_Process *proc; 1145 struct GNUNET_OS_Process *proc;
970 1146
1147 if (plugin->internal_address == NULL)
1148 {
1149 GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING,
1150 "tcp",
1151 _("Internal IP address not known, cannot use ICMP NAT traversal method\n"));
1152 return;
1153 }
971 GNUNET_assert (sa->sin_family == AF_INET); 1154 GNUNET_assert (sa->sin_family == AF_INET);
972 if (NULL == inet_ntop (AF_INET, 1155 if (NULL == inet_ntop (AF_INET,
973 &sa->sin_addr, 1156 &sa->sin_addr,
@@ -984,7 +1167,7 @@ run_gnunet_nat_client (struct Plugin *plugin,
984 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, 1167 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG,
985 "tcp", 1168 "tcp",
986 _("Running gnunet-nat-client %s %s %u\n"), 1169 _("Running gnunet-nat-client %s %s %u\n"),
987 plugin->external_address, 1170 plugin->internal_address,
988 inet4, 1171 inet4,
989 (unsigned int) plugin->adv_port); 1172 (unsigned int) plugin->adv_port);
990#endif 1173#endif
@@ -992,7 +1175,7 @@ run_gnunet_nat_client (struct Plugin *plugin,
992 NULL, 1175 NULL,
993 "gnunet-nat-client", 1176 "gnunet-nat-client",
994 "gnunet-nat-client", 1177 "gnunet-nat-client",
995 plugin->external_address, 1178 plugin->internal_address,
996 inet4, 1179 inet4,
997 port_as_string, 1180 port_as_string,
998 NULL); 1181 NULL);
@@ -1190,7 +1373,7 @@ tcp_plugin_send (void *cls,
1190 session = create_session (plugin, 1373 session = create_session (plugin,
1191 target, 1374 target,
1192 NULL, 1375 NULL,
1193 is_natd); 1376 GNUNET_YES);
1194 1377
1195 /* create new message entry */ 1378 /* create new message entry */
1196 pm = GNUNET_malloc (sizeof (struct PendingMessage) + msgbuf_size); 1379 pm = GNUNET_malloc (sizeof (struct PendingMessage) + msgbuf_size);
@@ -1258,7 +1441,7 @@ tcp_plugin_send (void *cls,
1258 target, 1441 target,
1259 GNUNET_SERVER_connect_socket (plugin->server, 1442 GNUNET_SERVER_connect_socket (plugin->server,
1260 sa), 1443 sa),
1261 is_natd); 1444 GNUNET_NO);
1262 session->connect_addr = GNUNET_malloc (addrlen); 1445 session->connect_addr = GNUNET_malloc (addrlen);
1263 memcpy (session->connect_addr, 1446 memcpy (session->connect_addr,
1264 addr, 1447 addr,
@@ -1471,22 +1654,19 @@ tcp_plugin_address_pretty_printer (void *cls,
1471 1654
1472 1655
1473/** 1656/**
1474 * Check if the given port is plausible (must be either 1657 * Check if the given port is plausible (must be either our listen
1475 * our listen port or our advertised port). If it is 1658 * port or our advertised port), or any port if we are behind NAT
1476 * neither, we return GNUNET_SYSERR. 1659 * and do not have a port open. If it is neither, we return
1660 * GNUNET_SYSERR.
1477 * 1661 *
1478 * @param plugin global variables 1662 * @param plugin global variables
1479 * @param in_port port number to check 1663 * @param in_port port number to check
1480 * @return GNUNET_OK if port is either open_port or adv_port 1664 * @return GNUNET_OK if port is either open_port or adv_port
1481 */ 1665 */
1482static int 1666static int
1483check_port (struct Plugin *plugin, uint16_t in_port) 1667check_port (struct Plugin *plugin,
1668 uint16_t in_port)
1484{ 1669{
1485 if ( (plugin->behind_nat == GNUNET_YES) && (in_port == 0) )
1486 return GNUNET_OK;
1487 if ( (plugin->only_nat_addresses == GNUNET_YES) &&
1488 (plugin->behind_nat == GNUNET_YES) )
1489 return GNUNET_SYSERR; /* odd case... */
1490 if ((in_port == plugin->adv_port) || (in_port == plugin->open_port)) 1670 if ((in_port == plugin->adv_port) || (in_port == plugin->open_port))
1491 return GNUNET_OK; 1671 return GNUNET_OK;
1492 return GNUNET_SYSERR; 1672 return GNUNET_SYSERR;
@@ -1526,11 +1706,14 @@ tcp_plugin_check_address (void *cls,
1526 if (addrlen == sizeof (struct IPv4TcpAddress)) 1706 if (addrlen == sizeof (struct IPv4TcpAddress))
1527 { 1707 {
1528 v4 = (struct IPv4TcpAddress *) addr; 1708 v4 = (struct IPv4TcpAddress *) addr;
1709 if (GNUNET_OK ==
1710 check_mapped_addr (plugin, v4, sizeof (struct IPv4TcpAddress)))
1711 return GNUNET_OK;
1529 if (GNUNET_OK != 1712 if (GNUNET_OK !=
1530 check_port (plugin, ntohs (v4->t_port))) 1713 check_port (plugin, ntohs (v4->t_port)))
1531 return GNUNET_SYSERR; 1714 return GNUNET_SYSERR;
1532 if (GNUNET_OK != 1715 if (GNUNET_OK !=
1533 check_local_addr (plugin, &v4->ipv4_addr, sizeof (uint32_t))) 1716 check_local_addr (plugin, &v4->ipv4_addr, sizeof (struct in_addr)))
1534 return GNUNET_SYSERR; 1717 return GNUNET_SYSERR;
1535 } 1718 }
1536 else 1719 else
@@ -1541,6 +1724,9 @@ tcp_plugin_check_address (void *cls,
1541 GNUNET_break_op (0); 1724 GNUNET_break_op (0);
1542 return GNUNET_SYSERR; 1725 return GNUNET_SYSERR;
1543 } 1726 }
1727 if (GNUNET_OK ==
1728 check_mapped_addr (plugin, v6, sizeof (struct IPv6TcpAddress)))
1729 return GNUNET_OK;
1544 if (GNUNET_OK != 1730 if (GNUNET_OK !=
1545 check_port (plugin, ntohs (v6->t6_port))) 1731 check_port (plugin, ntohs (v6->t6_port)))
1546 return GNUNET_SYSERR; 1732 return GNUNET_SYSERR;
@@ -1630,9 +1816,8 @@ handle_tcp_nat_probe (void *cls,
1630#if DEBUG_TCP_NAT 1816#if DEBUG_TCP_NAT
1631 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, 1817 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG,
1632 "tcp", 1818 "tcp",
1633 "handle_tcp_nat_probe Found address `%s' for incoming connection %p\n", 1819 "Found address `%s' for incoming connection\n",
1634 GNUNET_a2s (vaddr, alen), 1820 GNUNET_a2s (vaddr, alen));
1635 client);
1636#endif 1821#endif
1637 switch (((const struct sockaddr *)vaddr)->sa_family) 1822 switch (((const struct sockaddr *)vaddr)->sa_family)
1638 { 1823 {
@@ -1706,9 +1891,9 @@ handle_tcp_welcome (void *cls,
1706#if DEBUG_TCP 1891#if DEBUG_TCP
1707 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, 1892 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG,
1708 "tcp", 1893 "tcp",
1709 "Received %s message from a `%4s/%p'.\n", 1894 "Received %s message from `%4s'.\n",
1710 "WELCOME", 1895 "WELCOME",
1711 GNUNET_i2s (&wm->clientIdentity), client); 1896 GNUNET_i2s (&wm->clientIdentity));
1712#endif 1897#endif
1713 GNUNET_STATISTICS_update (plugin->env->stats, 1898 GNUNET_STATISTICS_update (plugin->env->stats,
1714 gettext_noop ("# TCP WELCOME messages received"), 1899 gettext_noop ("# TCP WELCOME messages received"),
@@ -1721,9 +1906,9 @@ handle_tcp_welcome (void *cls,
1721#if DEBUG_TCP_NAT 1906#if DEBUG_TCP_NAT
1722 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, 1907 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG,
1723 "tcp", 1908 "tcp",
1724 "Received %s message from a `%4s/%p', creating session\n", 1909 "Received %s message from a `%4s', creating new session\n",
1725 "WELCOME", 1910 "WELCOME",
1726 GNUNET_i2s (&wm->clientIdentity), client); 1911 GNUNET_i2s (&wm->clientIdentity));
1727#endif 1912#endif
1728 GNUNET_SERVER_client_keep (client); 1913 GNUNET_SERVER_client_keep (client);
1729 session = create_session (plugin, 1914 session = create_session (plugin,
@@ -1737,9 +1922,8 @@ handle_tcp_welcome (void *cls,
1737#if DEBUG_TCP_NAT 1922#if DEBUG_TCP_NAT
1738 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, 1923 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG,
1739 "tcp", 1924 "tcp",
1740 "Found address `%s' for incoming connection %p\n", 1925 "Found address `%s' for incoming connection\n",
1741 GNUNET_a2s (vaddr, alen), 1926 GNUNET_a2s (vaddr, alen));
1742 client);
1743#endif 1927#endif
1744 if (alen == sizeof (struct sockaddr_in)) 1928 if (alen == sizeof (struct sockaddr_in))
1745 { 1929 {
@@ -1772,12 +1956,6 @@ handle_tcp_welcome (void *cls,
1772 "Did not obtain TCP socket address for incoming connection\n"); 1956 "Did not obtain TCP socket address for incoming connection\n");
1773#endif 1957#endif
1774 } 1958 }
1775#if DEBUG_TCP
1776 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG,
1777 "tcp",
1778 "Creating new session %p for connection %p\n",
1779 session, client);
1780#endif
1781 process_pending_messages (session); 1959 process_pending_messages (session);
1782 } 1960 }
1783 else 1961 else
@@ -1788,9 +1966,8 @@ handle_tcp_welcome (void *cls,
1788 { 1966 {
1789 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, 1967 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG,
1790 "tcp", 1968 "tcp",
1791 "Found address `%s' (already have session) for incoming connection %p\n", 1969 "Found address `%s' (already have session)\n",
1792 GNUNET_a2s (vaddr, alen), 1970 GNUNET_a2s (vaddr, alen));
1793 client);
1794 } 1971 }
1795#endif 1972#endif
1796 } 1973 }
@@ -1914,13 +2091,12 @@ disconnect_notify (void *cls,
1914#if DEBUG_TCP 2091#if DEBUG_TCP
1915 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, 2092 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG,
1916 "tcp", 2093 "tcp",
1917 "Destroying session of `%4s' with %s (%p) due to network-level disconnect.\n", 2094 "Destroying session of `%4s' with %s due to network-level disconnect.\n",
1918 GNUNET_i2s (&session->target), 2095 GNUNET_i2s (&session->target),
1919 (session->connect_addr != NULL) ? 2096 (session->connect_addr != NULL) ?
1920 tcp_address_to_string (session->plugin, 2097 tcp_address_to_string (session->plugin,
1921 session->connect_addr, 2098 session->connect_addr,
1922 session->connect_alen) : "*", 2099 session->connect_alen) : "*");
1923 client);
1924#endif 2100#endif
1925 disconnect_session (session); 2101 disconnect_session (session);
1926} 2102}
@@ -1928,7 +2104,7 @@ disconnect_notify (void *cls,
1928 2104
1929/** 2105/**
1930 * Add the IP of our network interface to the list of 2106 * Add the IP of our network interface to the list of
1931 * our external IP addresses. 2107 * our internal IP addresses.
1932 * 2108 *
1933 * @param cls the 'struct Plugin*' 2109 * @param cls the 'struct Plugin*'
1934 * @param name name of the interface 2110 * @param name name of the interface
@@ -1962,28 +2138,31 @@ process_interfaces (void *cls,
1962 t4.ipv4_addr = ((struct sockaddr_in *) addr)->sin_addr.s_addr; 2138 t4.ipv4_addr = ((struct sockaddr_in *) addr)->sin_addr.s_addr;
1963 GNUNET_assert (NULL != inet_ntop(AF_INET, 2139 GNUNET_assert (NULL != inet_ntop(AF_INET,
1964 &t4.ipv4_addr, 2140 &t4.ipv4_addr,
1965 &buf[0], 2141 buf,
1966 INET_ADDRSTRLEN)); 2142 sizeof (buf)));
1967 if ( (plugin->bind_address != NULL) && 2143 if ( (plugin->bind_address != NULL) &&
1968 (0 != strcmp(buf, plugin->bind_address)) ) 2144 (0 != strcmp(buf, plugin->bind_address)) )
1969 { 2145 {
2146#if DEBUG_TCP
1970 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, 2147 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG,
1971 "tcp", 2148 "tcp",
1972 "Not notifying transport of address %s\n", 2149 "Not notifying transport of address `%s' (redundant)\n",
1973 GNUNET_a2s (addr, addrlen)); 2150 GNUNET_a2s (addr, addrlen));
2151#endif
1974 return GNUNET_OK; 2152 return GNUNET_OK;
1975 } 2153 }
1976 add_to_address_list (plugin, &t4.ipv4_addr, sizeof (uint32_t)); 2154 if ( (plugin->internal_address == NULL) &&
1977 if ((plugin->behind_nat == GNUNET_YES) && (plugin->only_nat_addresses == GNUNET_YES)) 2155 (isDefault) )
1978 t4.t_port = htons(0); 2156 plugin->internal_address = GNUNET_strdup (buf);
1979 else if (plugin->behind_nat == GNUNET_YES) /* We are behind NAT, but will advertise NAT and normal addresses */ 2157 add_to_address_list (plugin, &t4.ipv4_addr, sizeof (struct in_addr));
2158 if (plugin->behind_nat == GNUNET_YES)
1980 { 2159 {
2160 /* Also advertise as NAT (with port 0) */
1981 t4_nat.ipv4_addr = ((struct sockaddr_in *) addr)->sin_addr.s_addr; 2161 t4_nat.ipv4_addr = ((struct sockaddr_in *) addr)->sin_addr.s_addr;
1982 t4_nat.t_port = htons(plugin->adv_port); 2162 t4_nat.t_port = htons(0);
1983 arg_nat = &t4_nat; 2163 arg_nat = &t4_nat;
1984 } 2164 }
1985 else 2165 t4.t_port = htons (plugin->adv_port);
1986 t4.t_port = htons (plugin->adv_port);
1987 arg = &t4; 2166 arg = &t4;
1988 args = sizeof (t4); 2167 args = sizeof (t4);
1989 break; 2168 break;
@@ -1999,20 +2178,19 @@ process_interfaces (void *cls,
1999 memcpy (&t6.ipv6_addr, 2178 memcpy (&t6.ipv6_addr,
2000 &((struct sockaddr_in6 *) addr)->sin6_addr, 2179 &((struct sockaddr_in6 *) addr)->sin6_addr,
2001 sizeof (struct in6_addr)); 2180 sizeof (struct in6_addr));
2002 add_to_address_list (plugin, &t6.ipv6_addr, sizeof (struct in6_addr)); 2181 add_to_address_list (plugin,
2003 if ( (plugin->behind_nat == GNUNET_YES) && 2182 &t6.ipv6_addr,
2004 (plugin->only_nat_addresses == GNUNET_YES) ) 2183 sizeof (struct in6_addr));
2005 t6.t6_port = htons(0); 2184 if (plugin->behind_nat == GNUNET_YES)
2006 else if (plugin->behind_nat == GNUNET_YES) /* We are behind NAT, but will advertise NAT and normal addresses */
2007 { 2185 {
2186 /* Also advertise as NAT (with port 0) */
2008 memcpy (&t6_nat.ipv6_addr, 2187 memcpy (&t6_nat.ipv6_addr,
2009 &((struct sockaddr_in6 *) addr)->sin6_addr, 2188 &((struct sockaddr_in6 *) addr)->sin6_addr,
2010 sizeof (struct in6_addr)); 2189 sizeof (struct in6_addr));
2011 t6_nat.t6_port = htons(plugin->adv_port); 2190 t6_nat.t6_port = htons(0);
2012 arg_nat = &t6; 2191 arg_nat = &t6;
2013 } 2192 }
2014 else 2193 t6.t6_port = htons (plugin->adv_port);
2015 t6.t6_port = htons (plugin->adv_port);
2016 arg = &t6; 2194 arg = &t6;
2017 args = sizeof (t6); 2195 args = sizeof (t6);
2018 break; 2196 break;
@@ -2084,11 +2262,19 @@ notify_send_probe (void *cls,
2084 void *buf) 2262 void *buf)
2085{ 2263{
2086 struct TCPProbeContext *tcp_probe_ctx = cls; 2264 struct TCPProbeContext *tcp_probe_ctx = cls;
2265 struct Plugin *plugin = tcp_probe_ctx->plugin;
2087 size_t ret; 2266 size_t ret;
2088 2267
2089 tcp_probe_ctx->transmit_handle = NULL; 2268 tcp_probe_ctx->transmit_handle = NULL;
2269 GNUNET_CONTAINER_DLL_remove (plugin->probe_head,
2270 plugin->probe_tail,
2271 tcp_probe_ctx);
2090 if (buf == NULL) 2272 if (buf == NULL)
2091 return 0; 2273 {
2274 GNUNET_CONNECTION_destroy (tcp_probe_ctx->sock, GNUNET_NO);
2275 GNUNET_free(tcp_probe_ctx);
2276 return 0;
2277 }
2092 GNUNET_assert(size >= sizeof(tcp_probe_ctx->message)); 2278 GNUNET_assert(size >= sizeof(tcp_probe_ctx->message));
2093 memcpy(buf, &tcp_probe_ctx->message, sizeof(tcp_probe_ctx->message)); 2279 memcpy(buf, &tcp_probe_ctx->message, sizeof(tcp_probe_ctx->message));
2094 GNUNET_SERVER_connect_socket (tcp_probe_ctx->plugin->server, 2280 GNUNET_SERVER_connect_socket (tcp_probe_ctx->plugin->server,
@@ -2219,6 +2405,9 @@ tcp_plugin_server_read (void *cls,
2219 sizeof(struct GNUNET_PeerIdentity)); 2405 sizeof(struct GNUNET_PeerIdentity));
2220 tcp_probe_ctx->plugin = plugin; 2406 tcp_probe_ctx->plugin = plugin;
2221 tcp_probe_ctx->sock = sock; 2407 tcp_probe_ctx->sock = sock;
2408 GNUNET_CONTAINER_DLL_insert (plugin->probe_head,
2409 plugin->probe_tail,
2410 tcp_probe_ctx);
2222 tcp_probe_ctx->transmit_handle 2411 tcp_probe_ctx->transmit_handle
2223 = GNUNET_CONNECTION_notify_transmit_ready (sock, 2412 = GNUNET_CONNECTION_notify_transmit_ready (sock,
2224 ntohs (tcp_probe_ctx->message.header.size), 2413 ntohs (tcp_probe_ctx->message.header.size),
@@ -2237,12 +2426,13 @@ tcp_plugin_server_read (void *cls,
2237 * Start the gnunet-nat-server process for users behind NAT. 2426 * Start the gnunet-nat-server process for users behind NAT.
2238 * 2427 *
2239 * @param plugin the transport plugin 2428 * @param plugin the transport plugin
2240 *
2241 * @return GNUNET_YES if process was started, GNUNET_SYSERR on error 2429 * @return GNUNET_YES if process was started, GNUNET_SYSERR on error
2242 */ 2430 */
2243static int 2431static int
2244tcp_transport_start_nat_server(struct Plugin *plugin) 2432tcp_transport_start_nat_server (struct Plugin *plugin)
2245{ 2433{
2434 if (plugin->internal_address == NULL)
2435 return GNUNET_SYSERR;
2246 plugin->server_stdout = GNUNET_DISK_pipe (GNUNET_YES, 2436 plugin->server_stdout = GNUNET_DISK_pipe (GNUNET_YES,
2247 GNUNET_NO, 2437 GNUNET_NO,
2248 GNUNET_YES); 2438 GNUNET_YES);
@@ -2349,7 +2539,7 @@ get_path_from_PATH (const char *binary)
2349 * GNUNET_SYSERR on error 2539 * GNUNET_SYSERR on error
2350 */ 2540 */
2351static int 2541static int
2352check_gnunet_nat_binary(const char *binary) 2542check_gnunet_nat_binary (const char *binary)
2353{ 2543{
2354 struct stat statbuf; 2544 struct stat statbuf;
2355 char *p; 2545 char *p;
@@ -2401,6 +2591,7 @@ check_gnunet_nat_binary(const char *binary)
2401#endif 2591#endif
2402} 2592}
2403 2593
2594
2404/** 2595/**
2405 * Entry point for the plugin. 2596 * Entry point for the plugin.
2406 * 2597 *
@@ -2426,75 +2617,46 @@ libgnunet_plugin_transport_tcp_init (void *cls)
2426 unsigned int i; 2617 unsigned int i;
2427 int behind_nat; 2618 int behind_nat;
2428 int allow_nat; 2619 int allow_nat;
2429 int only_nat_addresses;
2430 char *internal_address; 2620 char *internal_address;
2431 char *external_address; 2621 char *external_address;
2432 struct sockaddr_in in_addr; 2622 struct sockaddr_in in_addr;
2433 struct IPv4TcpAddress t4; 2623 struct IPv4TcpAddress t4;
2434 2624 struct GNUNET_TIME_Relative idle_timeout;
2435 service = GNUNET_SERVICE_start ("transport-tcp", env->cfg);
2436 if (service == NULL)
2437 {
2438 GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING,
2439 "tcp",
2440 _("Failed to start service.\n"));
2441 return NULL;
2442 }
2443 2625
2444 behind_nat = GNUNET_CONFIGURATION_get_value_yesno (env->cfg, 2626 behind_nat = GNUNET_CONFIGURATION_get_value_yesno (env->cfg,
2445 "transport-tcp", 2627 "transport-tcp",
2446 "BEHIND_NAT"); 2628 "BEHIND_NAT");
2447 if (GNUNET_YES == behind_nat) 2629 if ( (GNUNET_YES == behind_nat) &&
2630 (GNUNET_YES != check_gnunet_nat_binary("gnunet-nat-server")) )
2448 { 2631 {
2449 /* We are behind nat (according to the user) */ 2632 behind_nat = GNUNET_NO;
2450 if (check_gnunet_nat_binary("gnunet-nat-server") == GNUNET_YES) 2633 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2451 { 2634 _("Configuration requires `%s', but binary is not installed properly (SUID bit not set). Option disabled.\n"),
2452 behind_nat = GNUNET_YES; 2635 "gnunet-nat-server");
2453 }
2454 else
2455 {
2456 behind_nat = GNUNET_NO;
2457 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2458 _("Configuration specified you are behind a NAT, but %s is not installed properly (SUID bit not set)!\n"),
2459 "gnunet-nat-server");
2460 }
2461 } 2636 }
2637
2462 allow_nat = GNUNET_CONFIGURATION_get_value_yesno (env->cfg, 2638 allow_nat = GNUNET_CONFIGURATION_get_value_yesno (env->cfg,
2463 "transport-tcp", 2639 "transport-tcp",
2464 "ALLOW_NAT"); 2640 "ALLOW_NAT");
2465 if (GNUNET_YES == allow_nat) 2641 if ( (GNUNET_YES == allow_nat) &&
2642 (GNUNET_YES != check_gnunet_nat_binary("gnunet-nat-client")) )
2466 { 2643 {
2467 if (check_gnunet_nat_binary("gnunet-nat-client") == GNUNET_YES) 2644 allow_nat = GNUNET_NO;
2468 { 2645 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2469 allow_nat = GNUNET_YES; /* We will try to connect to NAT'd peers */ 2646 _("Configuration requires `%s', but binary is not installed properly (SUID bit not set). Option disabled.\n"),
2470 } 2647 "gnunet-nat-client");
2471 else
2472 {
2473 allow_nat = GNUNET_NO;
2474 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2475 _("Configuration specified you want to connect to NATed peers, but %s is not installed properly (SUID bit not set)!\n"),
2476 "gnunet-nat-client");
2477 }
2478 } 2648 }
2479 2649
2480 only_nat_addresses = GNUNET_CONFIGURATION_get_value_yesno (env->cfg,
2481 "transport-tcp",
2482 "ONLY_NAT_ADDRESSES");
2483
2484 external_address = NULL; 2650 external_address = NULL;
2485 if ( ( (GNUNET_YES == behind_nat) || 2651 if (GNUNET_OK ==
2486 (GNUNET_YES == allow_nat) ) && 2652 GNUNET_CONFIGURATION_have_value (env->cfg,
2487 (GNUNET_OK != 2653 "transport-tcp",
2488 GNUNET_CONFIGURATION_get_value_string (env->cfg, 2654 "EXTERNAL_ADDRESS"))
2489 "transport-tcp",
2490 "EXTERNAL_ADDRESS",
2491 &external_address)) )
2492 { 2655 {
2493 GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, 2656 (void) GNUNET_CONFIGURATION_get_value_string (env->cfg,
2494 "tcp", 2657 "transport-tcp",
2495 _("EXTERNAL_ADDRESS option required in configuration (either BEHIND_NAT or ALLOW_NAT set to YES)!\n")); 2658 "EXTERNAL_ADDRESS",
2496 GNUNET_SERVICE_stop (service); 2659 &external_address);
2497 return NULL;
2498 } 2660 }
2499 2661
2500 if ( (external_address != NULL) && 2662 if ( (external_address != NULL) &&
@@ -2505,22 +2667,19 @@ libgnunet_plugin_transport_tcp_init (void *cls)
2505 _("Malformed %s `%s' given in configuration!\n"), 2667 _("Malformed %s `%s' given in configuration!\n"),
2506 "EXTERNAL_ADDRESS", 2668 "EXTERNAL_ADDRESS",
2507 external_address); 2669 external_address);
2670 return NULL;
2508 } 2671 }
2509 2672
2510 internal_address = NULL; 2673 internal_address = NULL;
2511 if ( (GNUNET_YES == behind_nat) && 2674 if (GNUNET_OK ==
2512 (GNUNET_OK != 2675 GNUNET_CONFIGURATION_have_value (env->cfg,
2513 GNUNET_CONFIGURATION_get_value_string (env->cfg, 2676 "transport-tcp",
2514 "transport-tcp", 2677 "INTERNAL_ADDRESS"))
2515 "INTERNAL_ADDRESS",
2516 &internal_address)) )
2517 { 2678 {
2518 GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, 2679 (void) GNUNET_CONFIGURATION_get_value_string (env->cfg,
2519 "tcp", 2680 "transport-tcp",
2520 _("Require INTERNAL_ADDRESS in configuration!\n")); 2681 "INTERNAL_ADDRESS",
2521 GNUNET_SERVICE_stop (service); 2682 &internal_address);
2522 GNUNET_free_non_null(external_address);
2523 return NULL;
2524 } 2683 }
2525 2684
2526 if ( (internal_address != NULL) && 2685 if ( (internal_address != NULL) &&
@@ -2531,6 +2690,9 @@ libgnunet_plugin_transport_tcp_init (void *cls)
2531 _("Malformed %s `%s' given in configuration!\n"), 2690 _("Malformed %s `%s' given in configuration!\n"),
2532 "INTERNAL_ADDRESS", 2691 "INTERNAL_ADDRESS",
2533 internal_address); 2692 internal_address);
2693 GNUNET_free_non_null(internal_address);
2694 GNUNET_free_non_null(external_address);
2695 return NULL;
2534 } 2696 }
2535 2697
2536 aport = 0; 2698 aport = 0;
@@ -2553,12 +2715,28 @@ libgnunet_plugin_transport_tcp_init (void *cls)
2553 "transport-tcp"); 2715 "transport-tcp");
2554 GNUNET_free_non_null(external_address); 2716 GNUNET_free_non_null(external_address);
2555 GNUNET_free_non_null(internal_address); 2717 GNUNET_free_non_null(internal_address);
2556 GNUNET_SERVICE_stop (service);
2557 return NULL; 2718 return NULL;
2558 } 2719 }
2559 2720
2560 if (aport == 0) 2721 if (aport == 0)
2561 aport = bport; 2722 aport = bport;
2723 if (bport == 0)
2724 aport = 0;
2725
2726 if (bport != 0)
2727 {
2728 service = GNUNET_SERVICE_start ("transport-tcp", env->cfg);
2729 if (service == NULL)
2730 {
2731 GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING,
2732 "tcp",
2733 _("Failed to start service.\n"));
2734 return NULL;
2735 }
2736 }
2737 else
2738 service = NULL;
2739
2562 plugin = GNUNET_malloc (sizeof (struct Plugin)); 2740 plugin = GNUNET_malloc (sizeof (struct Plugin));
2563 plugin->open_port = bport; 2741 plugin->open_port = bport;
2564 plugin->adv_port = aport; 2742 plugin->adv_port = aport;
@@ -2566,7 +2744,9 @@ libgnunet_plugin_transport_tcp_init (void *cls)
2566 plugin->internal_address = internal_address; 2744 plugin->internal_address = internal_address;
2567 plugin->behind_nat = behind_nat; 2745 plugin->behind_nat = behind_nat;
2568 plugin->allow_nat = allow_nat; 2746 plugin->allow_nat = allow_nat;
2569 plugin->only_nat_addresses = only_nat_addresses; 2747 plugin->allow_upnp = GNUNET_CONFIGURATION_get_value_yesno (env->cfg,
2748 "transport-tcp",
2749 "ENABLE_UPNP");
2570 plugin->env = env; 2750 plugin->env = env;
2571 plugin->lsock = NULL; 2751 plugin->lsock = NULL;
2572 api = GNUNET_malloc (sizeof (struct GNUNET_TRANSPORT_PluginFunctions)); 2752 api = GNUNET_malloc (sizeof (struct GNUNET_TRANSPORT_PluginFunctions));
@@ -2577,65 +2757,91 @@ libgnunet_plugin_transport_tcp_init (void *cls)
2577 api->check_address = &tcp_plugin_check_address; 2757 api->check_address = &tcp_plugin_check_address;
2578 api->address_to_string = &tcp_address_to_string; 2758 api->address_to_string = &tcp_address_to_string;
2579 plugin->service = service; 2759 plugin->service = service;
2580 plugin->server = GNUNET_SERVICE_get_server (service); 2760 if (service != NULL)
2761 {
2762 plugin->server = GNUNET_SERVICE_get_server (service);
2763 }
2764 else
2765 {
2766 if (GNUNET_OK !=
2767 GNUNET_CONFIGURATION_get_value_time (env->cfg,
2768 "transport-tcp",
2769 "TIMEOUT",
2770 &idle_timeout))
2771 {
2772 GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR,
2773 "tcp",
2774 _("Failed to find option %s in section %s!\n"),
2775 "TIMEOUT",
2776 "transport-tcp");
2777 GNUNET_free_non_null(external_address);
2778 GNUNET_free_non_null(internal_address);
2779 GNUNET_free (api);
2780 return NULL;
2781 }
2782 plugin->server = GNUNET_SERVER_create_with_sockets (NULL, NULL, NULL,
2783 idle_timeout, GNUNET_YES);
2784 }
2581 plugin->handlers = GNUNET_malloc (sizeof (my_handlers)); 2785 plugin->handlers = GNUNET_malloc (sizeof (my_handlers));
2582 memcpy (plugin->handlers, my_handlers, sizeof (my_handlers)); 2786 memcpy (plugin->handlers, my_handlers, sizeof (my_handlers));
2583 for (i = 0; 2787 for (i = 0;
2584 i < 2788 i < sizeof (my_handlers) / sizeof (struct GNUNET_SERVER_MessageHandler);
2585 sizeof (my_handlers) / sizeof (struct GNUNET_SERVER_MessageHandler);
2586 i++) 2789 i++)
2587 plugin->handlers[i].callback_cls = plugin; 2790 plugin->handlers[i].callback_cls = plugin;
2588 GNUNET_SERVER_add_handlers (plugin->server, plugin->handlers); 2791 GNUNET_SERVER_add_handlers (plugin->server, plugin->handlers);
2792 GNUNET_SERVER_disconnect_notify (plugin->server,
2793 &disconnect_notify,
2794 plugin);
2795 GNUNET_OS_network_interfaces_list (&process_interfaces, plugin);
2589 2796
2590 if (plugin->behind_nat == GNUNET_YES) 2797 if ( (plugin->behind_nat == GNUNET_YES) &&
2798 (GNUNET_YES != tcp_transport_start_nat_server(plugin)) )
2591 { 2799 {
2592 if (GNUNET_YES != tcp_transport_start_nat_server(plugin)) 2800 GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR,
2593 { 2801 "tcp",
2594 GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, 2802 _("Failed to start %s required for NAT in %s!\n"),
2595 "tcp", 2803 "gnunet-nat-server"
2596 _("Failed to start %s required for NAT in %s!\n"), 2804 "transport-tcp");
2597 "gnunet-nat-server" 2805 GNUNET_free_non_null(external_address);
2598 "transport-tcp"); 2806 GNUNET_free_non_null(internal_address);
2599 GNUNET_free_non_null(external_address); 2807 if (service != NULL)
2600 GNUNET_free_non_null(internal_address); 2808 GNUNET_SERVICE_stop (service);
2601 GNUNET_SERVICE_stop (service); 2809 else
2602 GNUNET_free (api); 2810 GNUNET_SERVER_destroy (plugin->server);
2603 return NULL; 2811 GNUNET_free (api);
2604 } 2812 return NULL;
2605 } 2813 }
2606 2814
2607 if (allow_nat == GNUNET_YES) 2815 if (allow_nat == GNUNET_YES)
2608 { 2816 {
2609 plugin->nat_wait_conns = GNUNET_CONTAINER_multihashmap_create(100); 2817 plugin->nat_wait_conns = GNUNET_CONTAINER_multihashmap_create(16);
2610 GNUNET_assert(plugin->nat_wait_conns != NULL); 2818 GNUNET_assert (plugin->nat_wait_conns != NULL);
2611 } 2819 }
2612 2820
2613 GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, 2821 if (bport != 0)
2614 "tcp", 2822 GNUNET_log_from (GNUNET_ERROR_TYPE_INFO,
2615 _("TCP transport listening on port %llu\n"), 2823 "tcp",
2616 bport); 2824 _("TCP transport listening on port %llu\n"),
2825 bport);
2826 else
2827 GNUNET_log_from (GNUNET_ERROR_TYPE_INFO,
2828 "tcp",
2829 _("TCP transport not listening on any port (client only)\n"));
2617 if (aport != bport) 2830 if (aport != bport)
2618 GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, 2831 GNUNET_log_from (GNUNET_ERROR_TYPE_INFO,
2619 "tcp", 2832 "tcp",
2620 _("TCP transport advertises itself as being on port %llu\n"), 2833 _("TCP transport advertises itself as being on port %llu\n"),
2621 aport); 2834 aport);
2622 GNUNET_SERVER_disconnect_notify (plugin->server,
2623 &disconnect_notify,
2624 plugin);
2625 2835
2626 if (GNUNET_YES == GNUNET_CONFIGURATION_get_value_string (env->cfg, 2836 if (GNUNET_YES == GNUNET_CONFIGURATION_get_value_string (env->cfg,
2627 "transport-tcp", 2837 "transport-tcp",
2628 "BINDTO", 2838 "BINDTO",
2629 &plugin->bind_address)) 2839 &plugin->bind_address))
2630 { 2840 {
2631 GNUNET_log(GNUNET_ERROR_TYPE_INFO, 2841 GNUNET_log_from (GNUNET_ERROR_TYPE_INFO,
2632 _("Binding TCP plugin to specific address: `%s'\n"), 2842 "tcp",
2633 plugin->bind_address); 2843 _("Binding TCP plugin to specific address: `%s'\n"),
2634 } 2844 plugin->bind_address);
2635
2636 if (plugin->behind_nat == GNUNET_NO)
2637 {
2638 GNUNET_OS_network_interfaces_list (&process_interfaces, plugin);
2639 } 2845 }
2640 2846
2641 plugin->hostname_dns = GNUNET_RESOLVER_hostname_resolve (env->cfg, 2847 plugin->hostname_dns = GNUNET_RESOLVER_hostname_resolve (env->cfg,
@@ -2644,34 +2850,33 @@ libgnunet_plugin_transport_tcp_init (void *cls)
2644 &process_hostname_ips, 2850 &process_hostname_ips,
2645 plugin); 2851 plugin);
2646 2852
2647 if ( (plugin->behind_nat == GNUNET_YES) && 2853 if ( (plugin->external_address != NULL) &&
2648 (inet_pton(AF_INET, plugin->external_address, &t4.ipv4_addr) == 1) ) 2854 (inet_pton(AF_INET,
2649 { 2855 plugin->external_address,
2650 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, 2856 &t4.ipv4_addr) == 1) )
2651 "tcp",
2652 "Notifying transport of address %s:0\n",
2653 plugin->external_address);
2654 t4.t_port = htons(0);
2655 add_to_address_list (plugin, &t4.ipv4_addr, sizeof (uint32_t));
2656 plugin->env->notify_address (plugin->env->cls,
2657 "tcp",
2658 &t4, sizeof(t4), GNUNET_TIME_UNIT_FOREVER_REL);
2659 }
2660 else if ((plugin->external_address != NULL) &&
2661 (inet_pton(AF_INET, plugin->external_address, &t4.ipv4_addr) == 1) )
2662 { 2857 {
2663 t4.t_port = htons(plugin->adv_port); 2858 if (plugin->behind_nat == GNUNET_YES)
2664 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, 2859 {
2665 "tcp", 2860 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG,
2666 "Notifying transport of address %s:%d\n", 2861 "tcp",
2667 plugin->external_address, 2862 "Notifying transport of address %s:0\n",
2668 plugin->adv_port); 2863 plugin->external_address);
2669 add_to_address_list (plugin, &t4.ipv4_addr, sizeof (uint32_t)); 2864 t4.t_port = htons(0);
2865 }
2866 else
2867 {
2868 t4.t_port = htons(plugin->adv_port);
2869 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG,
2870 "tcp",
2871 "Notifying transport of address %s:%d\n",
2872 plugin->external_address,
2873 plugin->adv_port);
2874 }
2875 add_to_address_list (plugin, &t4.ipv4_addr, sizeof (struct in_addr));
2670 plugin->env->notify_address (plugin->env->cls, 2876 plugin->env->notify_address (plugin->env->cls,
2671 "tcp", 2877 "tcp",
2672 &t4, sizeof(t4), GNUNET_TIME_UNIT_FOREVER_REL); 2878 &t4, sizeof(t4), GNUNET_TIME_UNIT_FOREVER_REL);
2673 } 2879 }
2674
2675 return api; 2880 return api;
2676} 2881}
2677 2882
@@ -2686,6 +2891,7 @@ libgnunet_plugin_transport_tcp_done (void *cls)
2686 struct Plugin *plugin = api->cls; 2891 struct Plugin *plugin = api->cls;
2687 struct Session *session; 2892 struct Session *session;
2688 struct LocalAddrList *lal; 2893 struct LocalAddrList *lal;
2894 struct TCPProbeContext *tcp_probe;
2689 2895
2690 while (NULL != (session = plugin->sessions)) 2896 while (NULL != (session = plugin->sessions))
2691 disconnect_session (session); 2897 disconnect_session (session);
@@ -2694,15 +2900,29 @@ libgnunet_plugin_transport_tcp_done (void *cls)
2694 GNUNET_RESOLVER_request_cancel (plugin->hostname_dns); 2900 GNUNET_RESOLVER_request_cancel (plugin->hostname_dns);
2695 plugin->hostname_dns = NULL; 2901 plugin->hostname_dns = NULL;
2696 } 2902 }
2697 GNUNET_SERVICE_stop (plugin->service); 2903 if (plugin->service != NULL)
2904 GNUNET_SERVICE_stop (plugin->service);
2905 else
2906 GNUNET_SERVER_destroy (plugin->server);
2698 GNUNET_free (plugin->handlers); 2907 GNUNET_free (plugin->handlers);
2699 while (NULL != (lal = plugin->lal_head)) 2908 while (NULL != (lal = plugin->lal_head))
2700 { 2909 {
2701 GNUNET_CONTAINER_DLL_remove (plugin->lal_head, 2910 GNUNET_CONTAINER_DLL_remove (plugin->lal_head,
2702 plugin->lal_tail, 2911 plugin->lal_tail,
2703 lal); 2912 lal);
2913 if (lal->nat != NULL)
2914 GNUNET_NAT_unregister (lal->nat);
2915 GNUNET_free_non_null (lal->external_nat_address);
2704 GNUNET_free (lal); 2916 GNUNET_free (lal);
2705 } 2917 }
2918 while (NULL != (tcp_probe = plugin->probe_head))
2919 {
2920 GNUNET_CONTAINER_DLL_remove (plugin->probe_head,
2921 plugin->probe_tail,
2922 tcp_probe);
2923 GNUNET_CONNECTION_destroy (tcp_probe->sock, GNUNET_NO);
2924 GNUNET_free (tcp_probe);
2925 }
2706 2926
2707 if (plugin->behind_nat == GNUNET_YES) 2927 if (plugin->behind_nat == GNUNET_YES)
2708 { 2928 {
diff --git a/src/transport/test_quota_compliance_tcp_peer1.conf b/src/transport/test_quota_compliance_tcp_peer1.conf
index e26781d30..fb3d91939 100644
--- a/src/transport/test_quota_compliance_tcp_peer1.conf
+++ b/src/transport/test_quota_compliance_tcp_peer1.conf
@@ -34,9 +34,15 @@ AUTOSTART = NO
34PORT = 4094 34PORT = 4094
35 35
36[transport-tcp] 36[transport-tcp]
37DISABLEV6 = YES
37TIMEOUT = 300000 38TIMEOUT = 300000
38PORT = 4094 39PORT = 4094
39BINDTO = 127.0.0.1 40BINDTO = 127.0.0.1
41ENABLE_UPNP = NO
42BEHIND_NAT = NO
43ALLOW_NAT = NO
44INTERNAL_ADDRESS = 127.0.0.1
45EXTERNAL_ADDRESS = 127.0.0.1
40 46
41[transport] 47[transport]
42plugins = tcp 48plugins = tcp
diff --git a/src/transport/test_quota_compliance_tcp_peer2.conf b/src/transport/test_quota_compliance_tcp_peer2.conf
index 245c9696e..f84a7a066 100644
--- a/src/transport/test_quota_compliance_tcp_peer2.conf
+++ b/src/transport/test_quota_compliance_tcp_peer2.conf
@@ -6,9 +6,15 @@ DEFAULTCONFIG = test_quota_compliance_tcp_peer2.conf
6PORT = 3094 6PORT = 3094
7 7
8[transport-tcp] 8[transport-tcp]
9DISABLEV6 = YES
9TIMEOUT = 300000 10TIMEOUT = 300000
10PORT = 3094 11PORT = 3094
11BINDTO = 127.0.0.1 12BINDTO = 127.0.0.1
13ENABLE_UPNP = NO
14BEHIND_NAT = NO
15ALLOW_NAT = NO
16INTERNAL_ADDRESS = 127.0.0.1
17EXTERNAL_ADDRESS = 127.0.0.1
12 18
13[fs] 19[fs]
14AUTOSTART = NO 20AUTOSTART = NO
diff --git a/src/transport/test_transport_api_tcp_nat_peer1.conf b/src/transport/test_transport_api_tcp_nat_peer1.conf
index c67570204..714686231 100644
--- a/src/transport/test_transport_api_tcp_nat_peer1.conf
+++ b/src/transport/test_transport_api_tcp_nat_peer1.conf
@@ -3,7 +3,6 @@ DISABLEV6 = YES
3PORT = 12368 3PORT = 12368
4BINDTO = 127.0.0.1 4BINDTO = 127.0.0.1
5BEHIND_NAT = YES 5BEHIND_NAT = YES
6ONLY_NAT_ADDRESSES = YES
7ALLOW_NAT = NO 6ALLOW_NAT = NO
8INTERNAL_ADDRESS = 127.0.0.1 7INTERNAL_ADDRESS = 127.0.0.1
9EXTERNAL_ADDRESS = 127.0.0.1 8EXTERNAL_ADDRESS = 127.0.0.1
diff --git a/src/transport/test_transport_api_tcp_peer1.conf b/src/transport/test_transport_api_tcp_peer1.conf
index 554f01246..e750ee011 100644
--- a/src/transport/test_transport_api_tcp_peer1.conf
+++ b/src/transport/test_transport_api_tcp_peer1.conf
@@ -2,11 +2,12 @@
2DISABLEV6 = YES 2DISABLEV6 = YES
3PORT = 12368 3PORT = 12368
4BINDTO = 127.0.0.1 4BINDTO = 127.0.0.1
5BEHIND_NAT = YES 5BEHIND_NAT = NO
6ONLY_NAT_ADDRESSES = YES
7ALLOW_NAT = NO 6ALLOW_NAT = NO
7ENABLE_UPNP = NO
8INTERNAL_ADDRESS = 127.0.0.1 8INTERNAL_ADDRESS = 127.0.0.1
9EXTERNAL_ADDRESS = 127.0.0.1 9EXTERNAL_ADDRESS = 127.0.0.1
10
10[fs] 11[fs]
11AUTOSTART = NO 12AUTOSTART = NO
12 13
diff --git a/src/transport/test_transport_api_tcp_peer2.conf b/src/transport/test_transport_api_tcp_peer2.conf
index 96ae620ca..40f0b0732 100644
--- a/src/transport/test_transport_api_tcp_peer2.conf
+++ b/src/transport/test_transport_api_tcp_peer2.conf
@@ -1,9 +1,10 @@
1[transport-tcp] 1[transport-tcp]
2DISABLEV6 = YES 2DISABLEV6 = YES
3PORT = 22368 3PORT = 0
4BINDTO = 127.0.0.1 4BINDTO = 127.0.0.1
5BEHIND_NAT = NO 5BEHIND_NAT = NO
6ALLOW_NAT = YES 6ALLOW_NAT = NO
7ENABLE_UPNP = NO
7EXTERNAL_ADDRESS = 127.0.0.1 8EXTERNAL_ADDRESS = 127.0.0.1
8INTERNAL_ADDRESS = 127.0.0.1 9INTERNAL_ADDRESS = 127.0.0.1
9 10