aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNathan S. Evans <evans@in.tum.de>2010-06-10 16:06:16 +0000
committerNathan S. Evans <evans@in.tum.de>2010-06-10 16:06:16 +0000
commit48cb1d395a3bf82e597366bf25e24fff21f39a32 (patch)
treecad1713194fc2b8ad005ec48eae462ce02c372d2
parent61b479ac0ad609646ee3dd1fa3ba84205ee95f09 (diff)
downloadgnunet-48cb1d395a3bf82e597366bf25e24fff21f39a32.tar.gz
gnunet-48cb1d395a3bf82e597366bf25e24fff21f39a32.zip
add support for using both NAT and non-NAT addresses, fix bug when multiple ICMP probes received
-rw-r--r--src/transport/plugin_transport_tcp.c65
-rw-r--r--src/transport/plugin_transport_udp.c64
-rw-r--r--src/transport/test_transport_api_udp_nat_peer1.conf1
3 files changed, 111 insertions, 19 deletions
diff --git a/src/transport/plugin_transport_tcp.c b/src/transport/plugin_transport_tcp.c
index cdaef4b48..7ad3a8e4b 100644
--- a/src/transport/plugin_transport_tcp.c
+++ b/src/transport/plugin_transport_tcp.c
@@ -380,6 +380,13 @@ struct Plugin
380 */ 380 */
381 int allow_nat; 381 int allow_nat;
382 382
383 /**
384 * Should this transport advertise only NAT addresses (port set to 0)?
385 * If not, all addresses will be duplicated for NAT punching and regular
386 * ports.
387 */
388 int only_nat_addresses;
389
383}; 390};
384 391
385 392
@@ -1080,7 +1087,7 @@ tcp_plugin_send (void *cls,
1080 session->pending_messages_tail, 1087 session->pending_messages_tail,
1081 pm); 1088 pm);
1082 1089
1083 GNUNET_CONTAINER_multihashmap_put(plugin->nat_wait_conns, &target->hashPubKey, session, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY); 1090 GNUNET_assert(GNUNET_CONTAINER_multihashmap_put(plugin->nat_wait_conns, &target->hashPubKey, session, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY) == GNUNET_OK);
1084#if DEBUG_TCP_NAT 1091#if DEBUG_TCP_NAT
1085 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, 1092 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG,
1086 "tcp", 1093 "tcp",
@@ -1451,6 +1458,7 @@ handle_tcp_nat_probe (void *cls,
1451#endif 1458#endif
1452 session = GNUNET_CONTAINER_multihashmap_get(plugin->nat_wait_conns, &tcp_nat_probe->clientIdentity.hashPubKey); 1459 session = GNUNET_CONTAINER_multihashmap_get(plugin->nat_wait_conns, &tcp_nat_probe->clientIdentity.hashPubKey);
1453 GNUNET_assert(session != NULL); 1460 GNUNET_assert(session != NULL);
1461 GNUNET_assert(GNUNET_CONTAINER_multihashmap_remove(plugin->nat_wait_conns, &tcp_nat_probe->clientIdentity.hashPubKey, session) == GNUNET_YES);
1454 GNUNET_SERVER_client_keep (client); 1462 GNUNET_SERVER_client_keep (client);
1455 session->client = client; 1463 session->client = client;
1456 session->last_activity = GNUNET_TIME_absolute_get (); 1464 session->last_activity = GNUNET_TIME_absolute_get ();
@@ -1493,21 +1501,13 @@ handle_tcp_nat_probe (void *cls,
1493 session->connect_alen = alen; 1501 session->connect_alen = alen;
1494 GNUNET_free (vaddr); 1502 GNUNET_free (vaddr);
1495 } 1503 }
1496 else
1497 {
1498 /* FIXME: free partial session? */
1499 }
1500 1504
1501 session->next = plugin->sessions; 1505 session->next = plugin->sessions;
1502 plugin->sessions = session; 1506 plugin->sessions = session;
1503
1504 GNUNET_STATISTICS_update (plugin->env->stats, 1507 GNUNET_STATISTICS_update (plugin->env->stats,
1505 gettext_noop ("# TCP sessions active"), 1508 gettext_noop ("# TCP sessions active"),
1506 1, 1509 1,
1507 GNUNET_NO); 1510 GNUNET_NO);
1508 /*GNUNET_SERVER_connect_socket (plugin->server,
1509 client->);*/
1510
1511 process_pending_messages (session); 1511 process_pending_messages (session);
1512 } 1512 }
1513 else 1513 else
@@ -1770,15 +1770,25 @@ process_interfaces (void *cls,
1770 int af; 1770 int af;
1771 struct IPv4TcpAddress t4; 1771 struct IPv4TcpAddress t4;
1772 struct IPv6TcpAddress t6; 1772 struct IPv6TcpAddress t6;
1773 struct IPv4TcpAddress t4_nat;
1774 struct IPv6TcpAddress t6_nat;
1773 void *arg; 1775 void *arg;
1774 uint16_t args; 1776 uint16_t args;
1777 void *arg_nat;
1775 1778
1776 af = addr->sa_family; 1779 af = addr->sa_family;
1780 arg_nat = NULL;
1777 if (af == AF_INET) 1781 if (af == AF_INET)
1778 { 1782 {
1779 t4.ipv4_addr = ((struct sockaddr_in *) addr)->sin_addr.s_addr; 1783 t4.ipv4_addr = ((struct sockaddr_in *) addr)->sin_addr.s_addr;
1780 if (plugin->behind_nat) 1784 if ((plugin->behind_nat == GNUNET_YES) && (plugin->only_nat_addresses == GNUNET_YES))
1781 t4.t_port = htons(0); 1785 t4.t_port = htons(0);
1786 else if (plugin->behind_nat == GNUNET_YES) /* We are behind NAT, but will advertise NAT and normal addresses */
1787 {
1788 t4_nat.ipv4_addr = ((struct sockaddr_in *) addr)->sin_addr.s_addr;
1789 t4_nat.t_port = htons(plugin->adv_port);
1790 arg_nat = &t4_nat;
1791 }
1782 else 1792 else
1783 t4.t_port = htons (plugin->adv_port); 1793 t4.t_port = htons (plugin->adv_port);
1784 arg = &t4; 1794 arg = &t4;
@@ -1794,8 +1804,16 @@ process_interfaces (void *cls,
1794 memcpy (&t6.ipv6_addr, 1804 memcpy (&t6.ipv6_addr,
1795 &((struct sockaddr_in6 *) addr)->sin6_addr, 1805 &((struct sockaddr_in6 *) addr)->sin6_addr,
1796 sizeof (struct in6_addr)); 1806 sizeof (struct in6_addr));
1797 if (plugin->behind_nat) 1807 if ((plugin->behind_nat == GNUNET_YES) && (plugin->only_nat_addresses == GNUNET_YES))
1798 t6.t6_port = htons(0); 1808 t6.t6_port = htons(0);
1809 else if (plugin->behind_nat == GNUNET_YES) /* We are behind NAT, but will advertise NAT and normal addresses */
1810 {
1811 memcpy (&t6_nat.ipv6_addr,
1812 &((struct sockaddr_in6 *) addr)->sin6_addr,
1813 sizeof (struct in6_addr));
1814 t6_nat.t6_port = htons(plugin->adv_port);
1815 arg_nat = &t6;
1816 }
1799 else 1817 else
1800 t6.t6_port = htons (plugin->adv_port); 1818 t6.t6_port = htons (plugin->adv_port);
1801 arg = &t6; 1819 arg = &t6;
@@ -1811,9 +1829,23 @@ process_interfaces (void *cls,
1811 "tcp", 1829 "tcp",
1812 _("Found address `%s' (%s)\n"), 1830 _("Found address `%s' (%s)\n"),
1813 GNUNET_a2s (addr, addrlen), name); 1831 GNUNET_a2s (addr, addrlen), name);
1832
1814 plugin->env->notify_address (plugin->env->cls, 1833 plugin->env->notify_address (plugin->env->cls,
1815 "tcp", 1834 "tcp",
1816 arg, args, GNUNET_TIME_UNIT_FOREVER_REL); 1835 arg, args, GNUNET_TIME_UNIT_FOREVER_REL);
1836
1837 if (arg_nat != NULL)
1838 {
1839 GNUNET_log_from (GNUNET_ERROR_TYPE_INFO |
1840 GNUNET_ERROR_TYPE_BULK,
1841 "tcp",
1842 _("Found address `%s' (%s)\n"),
1843 GNUNET_a2s (addr, addrlen), name);
1844 plugin->env->notify_address (plugin->env->cls,
1845 "tcp",
1846 arg_nat, args, GNUNET_TIME_UNIT_FOREVER_REL);
1847 }
1848
1817 return GNUNET_OK; 1849 return GNUNET_OK;
1818} 1850}
1819 1851
@@ -2119,6 +2151,7 @@ libgnunet_plugin_transport_tcp_init (void *cls)
2119 unsigned int i; 2151 unsigned int i;
2120 int behind_nat; 2152 int behind_nat;
2121 int allow_nat; 2153 int allow_nat;
2154 int only_nat_addresses;
2122 char *internal_address; 2155 char *internal_address;
2123 char *external_address; 2156 char *external_address;
2124 2157
@@ -2162,11 +2195,18 @@ libgnunet_plugin_transport_tcp_init (void *cls)
2162 allow_nat = GNUNET_NO; 2195 allow_nat = GNUNET_NO;
2163 GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING, "tcp", "Configuration specified you want to connect to NAT'd peers, but gnunet-nat-client is not installed properly (suid bit not set)!\n"); 2196 GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING, "tcp", "Configuration specified you want to connect to NAT'd peers, but gnunet-nat-client is not installed properly (suid bit not set)!\n");
2164 } 2197 }
2165
2166 } 2198 }
2167 else 2199 else
2168 allow_nat = GNUNET_NO; /* We don't want to try to help NAT'd peers */ 2200 allow_nat = GNUNET_NO; /* We don't want to try to help NAT'd peers */
2169 2201
2202
2203 if (GNUNET_YES == GNUNET_CONFIGURATION_get_value_yesno (env->cfg,
2204 "transport-tcp",
2205 "ONLY_NAT_ADDRESSES"))
2206 only_nat_addresses = GNUNET_YES; /* We will only report our addresses as NAT'd */
2207 else
2208 only_nat_addresses = GNUNET_NO; /* We will report our addresses as NAT'd and non-NAT'd */
2209
2170 external_address = NULL; 2210 external_address = NULL;
2171 if (((GNUNET_YES == behind_nat) || (GNUNET_YES == allow_nat)) && (GNUNET_OK != 2211 if (((GNUNET_YES == behind_nat) || (GNUNET_YES == allow_nat)) && (GNUNET_OK !=
2172 GNUNET_CONFIGURATION_get_value_string (env->cfg, 2212 GNUNET_CONFIGURATION_get_value_string (env->cfg,
@@ -2234,6 +2274,7 @@ libgnunet_plugin_transport_tcp_init (void *cls)
2234 plugin->internal_address = internal_address; 2274 plugin->internal_address = internal_address;
2235 plugin->behind_nat = behind_nat; 2275 plugin->behind_nat = behind_nat;
2236 plugin->allow_nat = allow_nat; 2276 plugin->allow_nat = allow_nat;
2277 plugin->only_nat_addresses = only_nat_addresses;
2237 plugin->env = env; 2278 plugin->env = env;
2238 plugin->lsock = NULL; 2279 plugin->lsock = NULL;
2239 api = GNUNET_malloc (sizeof (struct GNUNET_TRANSPORT_PluginFunctions)); 2280 api = GNUNET_malloc (sizeof (struct GNUNET_TRANSPORT_PluginFunctions));
diff --git a/src/transport/plugin_transport_udp.c b/src/transport/plugin_transport_udp.c
index 10bbf2972..ad8a70f0b 100644
--- a/src/transport/plugin_transport_udp.c
+++ b/src/transport/plugin_transport_udp.c
@@ -361,6 +361,13 @@ struct Plugin
361 int allow_nat; 361 int allow_nat;
362 362
363 /** 363 /**
364 * Should this transport advertise only NAT addresses (port set to 0)?
365 * If not, all addresses will be duplicated for NAT punching and regular
366 * ports.
367 */
368 int only_nat_addresses;
369
370 /**
364 * The process id of the server process (if behind NAT) 371 * The process id of the server process (if behind NAT)
365 */ 372 */
366 pid_t server_pid; 373 pid_t server_pid;
@@ -736,33 +743,67 @@ process_interfaces (void *cls,
736 int af; 743 int af;
737 struct sockaddr_in *v4; 744 struct sockaddr_in *v4;
738 struct sockaddr_in6 *v6; 745 struct sockaddr_in6 *v6;
746 struct sockaddr *addr_nat;
739 747
748 addr_nat = NULL;
740 af = addr->sa_family; 749 af = addr->sa_family;
741 if (af == AF_INET) 750 if (af == AF_INET)
742 { 751 {
743 v4 = (struct sockaddr_in *) addr; 752 v4 = (struct sockaddr_in *) addr;
744 if (plugin->behind_nat == GNUNET_YES) 753 if ((plugin->behind_nat == GNUNET_YES) && (plugin->only_nat_addresses == GNUNET_YES))
745 { 754 {
746 GNUNET_assert(inet_pton(AF_INET, plugin->external_address, &v4->sin_addr) == GNUNET_OK);
747 v4->sin_port = htons (0); /* Indicates to receiver we are behind NAT */ 755 v4->sin_port = htons (0); /* Indicates to receiver we are behind NAT */
748 } 756 }
757 else if (plugin->behind_nat == GNUNET_YES) /* We are behind NAT, but will advertise NAT and normal addresses */
758 {
759 addr_nat = GNUNET_malloc(addrlen);
760 memcpy(addr_nat, addr, addrlen);
761 v4 = (struct sockaddr_in *) addr_nat;
762 v4->sin_port = htons(plugin->port);
763 }
749 else 764 else
750 v4->sin_port = htons (plugin->port); 765 {
766 v4->sin_port = htons (plugin->port);
767 }
751 } 768 }
752 else 769 else
753 { 770 {
754 GNUNET_assert (af == AF_INET6); 771 GNUNET_assert (af == AF_INET6);
755 v6 = (struct sockaddr_in6 *) addr; 772 v6 = (struct sockaddr_in6 *) addr;
756 if (plugin->behind_nat == GNUNET_YES) 773 if ((plugin->behind_nat == GNUNET_YES) && (plugin->only_nat_addresses == GNUNET_YES))
757 v6->sin6_port = htons (0); 774 {
775 v6->sin6_port = htons (0);
776 }
777 else if (plugin->behind_nat == GNUNET_YES) /* We are behind NAT, but will advertise NAT and normal addresses */
778 {
779 addr_nat = GNUNET_malloc(addrlen);
780 memcpy(addr_nat, addr, addrlen);
781 v6 = (struct sockaddr_in6 *) addr_nat;
782 v6->sin6_port = htons(plugin->port);
783 }
758 else 784 else
759 v6->sin6_port = htons (plugin->port); 785 {
786 v6->sin6_port = htons (plugin->port);
787 }
760 } 788 }
761 789
762 GNUNET_log_from (GNUNET_ERROR_TYPE_INFO | 790 GNUNET_log_from (GNUNET_ERROR_TYPE_INFO |
763 GNUNET_ERROR_TYPE_BULK, 791 GNUNET_ERROR_TYPE_BULK,
764 "udp", _("Found address `%s' (%s)\n"), 792 "udp", _("Found address `%s' (%s)\n"),
765 GNUNET_a2s (addr, addrlen), name); 793 GNUNET_a2s (addr, addrlen), name);
794
795 if (addr_nat != NULL)
796 {
797 plugin->env->notify_address (plugin->env->cls,
798 "udp",
799 addr_nat, addrlen, GNUNET_TIME_UNIT_FOREVER_REL);
800 GNUNET_log_from (GNUNET_ERROR_TYPE_INFO |
801 GNUNET_ERROR_TYPE_BULK,
802 "udp", _("Found NAT address `%s' (%s)\n"),
803 GNUNET_a2s (addr_nat, addrlen), name);
804 GNUNET_free(addr_nat);
805 }
806
766 plugin->env->notify_address (plugin->env->cls, 807 plugin->env->notify_address (plugin->env->cls,
767 "udp", 808 "udp",
768 addr, addrlen, GNUNET_TIME_UNIT_FOREVER_REL); 809 addr, addrlen, GNUNET_TIME_UNIT_FOREVER_REL);
@@ -1626,6 +1667,7 @@ libgnunet_plugin_transport_udp_init (void *cls)
1626 int sockets_created; 1667 int sockets_created;
1627 int behind_nat; 1668 int behind_nat;
1628 int allow_nat; 1669 int allow_nat;
1670 int only_nat_addresses;
1629 char *internal_address; 1671 char *internal_address;
1630 char *external_address; 1672 char *external_address;
1631 1673
@@ -1670,6 +1712,13 @@ libgnunet_plugin_transport_udp_init (void *cls)
1670 else 1712 else
1671 allow_nat = GNUNET_NO; /* We don't want to try to help NAT'd peers */ 1713 allow_nat = GNUNET_NO; /* We don't want to try to help NAT'd peers */
1672 1714
1715 if (GNUNET_YES == GNUNET_CONFIGURATION_get_value_yesno (env->cfg,
1716 "transport-udp",
1717 "ONLY_NAT_ADDRESSES"))
1718 only_nat_addresses = GNUNET_YES; /* We will only report our addresses as NAT'd */
1719 else
1720 only_nat_addresses = GNUNET_NO; /* We will report our addresses as NAT'd and non-NAT'd */
1721
1673 external_address = NULL; 1722 external_address = NULL;
1674 if (((GNUNET_YES == behind_nat) || (GNUNET_YES == allow_nat)) && (GNUNET_OK != 1723 if (((GNUNET_YES == behind_nat) || (GNUNET_YES == allow_nat)) && (GNUNET_OK !=
1675 GNUNET_CONFIGURATION_get_value_string (env->cfg, 1724 GNUNET_CONFIGURATION_get_value_string (env->cfg,
@@ -1736,6 +1785,7 @@ libgnunet_plugin_transport_udp_init (void *cls)
1736 plugin->port = port; 1785 plugin->port = port;
1737 plugin->behind_nat = behind_nat; 1786 plugin->behind_nat = behind_nat;
1738 plugin->allow_nat = allow_nat; 1787 plugin->allow_nat = allow_nat;
1788 plugin->only_nat_addresses = only_nat_addresses;
1739 plugin->env = env; 1789 plugin->env = env;
1740 1790
1741 api = GNUNET_malloc (sizeof (struct GNUNET_TRANSPORT_PluginFunctions)); 1791 api = GNUNET_malloc (sizeof (struct GNUNET_TRANSPORT_PluginFunctions));
diff --git a/src/transport/test_transport_api_udp_nat_peer1.conf b/src/transport/test_transport_api_udp_nat_peer1.conf
index ef7316a35..149e3232f 100644
--- a/src/transport/test_transport_api_udp_nat_peer1.conf
+++ b/src/transport/test_transport_api_udp_nat_peer1.conf
@@ -2,6 +2,7 @@
2PORT = 12368 2PORT = 12368
3BEHIND_NAT = YES 3BEHIND_NAT = YES
4ALLOW_NAT = NO 4ALLOW_NAT = NO
5ONLY_NAT_ADDRESSES = YES
5INTERNAL_ADDRESS = 127.0.0.1 6INTERNAL_ADDRESS = 127.0.0.1
6EXTERNAL_ADDRESS = 127.0.0.1 7EXTERNAL_ADDRESS = 127.0.0.1
7 8