aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNathan S. Evans <evans@in.tum.de>2010-06-08 15:46:09 +0000
committerNathan S. Evans <evans@in.tum.de>2010-06-08 15:46:09 +0000
commit57a1e4caa0d9b6fee06e981b5b38cd6782489153 (patch)
tree89e9ca2410ea2b00ee7242aea661fc239d24f3f5
parentc728ce3b94baaa3812dbb853cd90343e9dac27f9 (diff)
downloadgnunet-57a1e4caa0d9b6fee06e981b5b38cd6782489153.tar.gz
gnunet-57a1e4caa0d9b6fee06e981b5b38cd6782489153.zip
somewhat simplified, somewhat working udp_nat implementation. let the buildbots thrash on it and see what happens
-rw-r--r--src/transport/plugin_transport_udp_nat.c509
1 files changed, 220 insertions, 289 deletions
diff --git a/src/transport/plugin_transport_udp_nat.c b/src/transport/plugin_transport_udp_nat.c
index a48e958ba..5f225a91c 100644
--- a/src/transport/plugin_transport_udp_nat.c
+++ b/src/transport/plugin_transport_udp_nat.c
@@ -26,17 +26,15 @@
26 * @author Nathan Evans 26 * @author Nathan Evans
27 * 27 *
28 * The idea with this transport is to connect gnunet peers to each other 28 * The idea with this transport is to connect gnunet peers to each other
29 * when one or both is behind a NAT. This is based on pwnat 29 * when ONE is behind a NAT. This is based on pwnat (http://samy.pl/pwnat)
30 * (http://samy.pl/pwnat) created by Samy Kamkar. This transport will 30 * created by Samy Kamkar. When configured with the PWNAT options, this
31 * take external IP addresses for a NAT'd peer, start a server daemon 31 * transport will start a server daemon which sends dummy ICMP and UDP
32 * which sends ICMP messages out to a predefined address. Then it forks 32 * messages out to a predefined address (typically 1.2.3.4).
33 * a client process which sends ICMP death messages to the given external 33 *
34 * IP address for the other peer (which has already also started the 34 * When a non-NAT'd peer (the client) learns of the NAT'd peer (the server)
35 * server). If everything works according to plan, the transport will 35 * address, it will send ICMP RESPONSES to the NAT'd peers external address.
36 * be given a port which has worked to punch into the other external 36 * The NAT box should forward these faked responses to the server, which
37 * addresses NAT to communicate with the other gnunet peer. Then keep 37 * can then connect directly to the non-NAT'd peer.
38 * alive messages will be sent every (???)ms or so to keep the tunnel
39 * safe.
40 */ 38 */
41 39
42#include "platform.h" 40#include "platform.h"
@@ -54,7 +52,9 @@
54#include "plugin_transport.h" 52#include "plugin_transport.h"
55#include "transport.h" 53#include "transport.h"
56 54
57#define DEBUG_UDP_NAT GNUNET_NO 55#define DEBUG_UDP_NAT GNUNET_YES
56
57#define MAX_PROBES 20
58 58
59/* 59/*
60 * Transport cost to peer, always 1 for UDP (direct connection) 60 * Transport cost to peer, always 1 for UDP (direct connection)
@@ -72,16 +72,9 @@ static struct GNUNET_RESOLVER_RequestHandle *hostname_dns;
72#define HOSTNAME_RESOLVE_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5) 72#define HOSTNAME_RESOLVE_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5)
73 73
74/** 74/**
75 * How many ports do we want to listen on (and send on) in order to get replies?
76 *
77 * FIXME: make this value dynamic, specified by configuration
78 */
79#define UDP_NAT_LISTEN_PORTS 257
80
81/**
82 * Starting port for listening and sending, eventually a config value 75 * Starting port for listening and sending, eventually a config value
83 */ 76 */
84#define UDP_NAT_STARTING_PORT 22086 77#define UDP_NAT_DEFAULT_PORT 22086
85 78
86/** 79/**
87 * UDP Message-Packet header. 80 * UDP Message-Packet header.
@@ -101,45 +94,6 @@ struct UDPMessage
101}; 94};
102 95
103 96
104/**
105 * UDP NAT Probe message definition
106 */
107struct UDP_NAT_ProbeMessage
108{
109 /**
110 * Message header
111 */
112 struct GNUNET_MessageHeader header;
113
114};
115
116/**
117 * UDP NAT Probe message reply definition
118 */
119struct UDP_NAT_ProbeMessageReply
120{
121 /**
122 * Message header
123 */
124 struct GNUNET_MessageHeader header;
125
126};
127
128
129/**
130 * UDP NAT Probe message confirm definition
131 */
132struct UDP_NAT_ProbeMessageConfirmation
133{
134 /**
135 * Message header
136 */
137 struct GNUNET_MessageHeader header;
138
139};
140
141
142
143/* Forward definition */ 97/* Forward definition */
144struct Plugin; 98struct Plugin;
145 99
@@ -190,6 +144,45 @@ struct MessageQueue
190}; 144};
191 145
192/** 146/**
147 * UDP NAT Probe message definition
148 */
149struct UDP_NAT_ProbeMessage
150{
151 /**
152 * Message header
153 */
154 struct GNUNET_MessageHeader header;
155
156};
157
158/**
159 * UDP NAT Probe message reply definition
160 */
161struct UDP_NAT_ProbeMessageReply
162{
163 /**
164 * Message header
165 */
166 struct GNUNET_MessageHeader header;
167
168};
169
170
171/**
172 * UDP NAT Probe message confirm definition
173 */
174struct UDP_NAT_ProbeMessageConfirmation
175{
176 /**
177 * Message header
178 */
179 struct GNUNET_MessageHeader header;
180
181};
182
183
184
185/**
193 * UDP NAT "Session" 186 * UDP NAT "Session"
194 */ 187 */
195struct PeerSession 188struct PeerSession
@@ -240,7 +233,6 @@ struct PeerSession
240 233
241}; 234};
242 235
243
244struct UDP_NAT_Probes 236struct UDP_NAT_Probes
245{ 237{
246 238
@@ -260,9 +252,9 @@ struct UDP_NAT_Probes
260 struct GNUNET_TIME_Absolute timeout; 252 struct GNUNET_TIME_Absolute timeout;
261 253
262 /** 254 /**
263 * Current index (which port to send on next basically) 255 * Count of how many probes we've attempted
264 */ 256 */
265 int index; 257 int count;
266 258
267 /** 259 /**
268 * The plugin this probe belongs to 260 * The plugin this probe belongs to
@@ -323,20 +315,9 @@ struct Plugin
323 GNUNET_SCHEDULER_TaskIdentifier select_task; 315 GNUNET_SCHEDULER_TaskIdentifier select_task;
324 316
325 /** 317 /**
326 * Starting port, will listen on num_ports (if available) starting 318 * Port to listen on.
327 * at this number (or will listen only on this port if non-nat'd)
328 */ 319 */
329 uint16_t starting_port; 320 uint16_t port;
330
331 /**
332 * Starting port for sending out crazy messages
333 */
334 uint32_t random_starting_port;
335
336 /**
337 * How many ports should we be using?
338 */
339 uint16_t num_ports;
340 321
341 /** 322 /**
342 * The external address given to us by the user. Must be actual 323 * The external address given to us by the user. Must be actual
@@ -401,7 +382,7 @@ struct UDP_Sock_Info
401/** 382/**
402 * the socket that we transmit all data with 383 * the socket that we transmit all data with
403 */ 384 */
404static struct UDP_Sock_Info *udp_nat_socks[UDP_NAT_LISTEN_PORTS]; 385static struct UDP_Sock_Info udp_nat_sock;
405 386
406 387
407/** 388/**
@@ -440,7 +421,6 @@ udp_nat_transport_server_stop (void *cls)
440 struct Plugin *plugin = cls; 421 struct Plugin *plugin = cls;
441 int ret; 422 int ret;
442 int ok; 423 int ok;
443 int i;
444 424
445 ret = 0; 425 ret = 0;
446 if (plugin->select_task != GNUNET_SCHEDULER_NO_TASK) 426 if (plugin->select_task != GNUNET_SCHEDULER_NO_TASK)
@@ -449,13 +429,12 @@ udp_nat_transport_server_stop (void *cls)
449 plugin->select_task = GNUNET_SCHEDULER_NO_TASK; 429 plugin->select_task = GNUNET_SCHEDULER_NO_TASK;
450 } 430 }
451 431
452 for (i = 0; i < plugin->num_ports; i++) 432
453 { 433 ok = GNUNET_NETWORK_socket_close (udp_nat_sock.desc);
454 ok = GNUNET_NETWORK_socket_close (udp_nat_socks[i]->desc); 434 if (ok == GNUNET_OK)
455 if (ok == GNUNET_OK) 435 udp_nat_sock.desc = NULL;
456 udp_nat_socks[i]->desc = NULL; 436 ret += ok;
457 ret += ok; 437
458 }
459 438
460 if (plugin->behind_nat == GNUNET_YES) 439 if (plugin->behind_nat == GNUNET_YES)
461 { 440 {
@@ -562,13 +541,14 @@ udp_nat_real_send (void *cls,
562 cont (cont_cls, target, GNUNET_OK); 541 cont (cont_cls, target, GNUNET_OK);
563 } 542 }
564 } 543 }
544
565 GNUNET_free (message); 545 GNUNET_free (message);
566 return sent; 546 return sent;
567} 547}
568 548
569/** 549/**
570 * We learned about a peer (possibly behind NAT) so run the 550 * We learned about a peer (possibly behind NAT) so run the
571 * gnunet-nat-client to send a dummy ICMP response 551 * gnunet-nat-client to send dummy ICMP responses
572 * 552 *
573 * @param plugin the plugin for this transport 553 * @param plugin the plugin for this transport
574 * @param addr the address of the peer 554 * @param addr the address of the peer
@@ -600,10 +580,10 @@ run_gnunet_nat_client (struct Plugin *plugin, const char *addr, size_t addrlen)
600 return; 580 return;
601 } 581 }
602 582
603 GNUNET_asprintf(&port_as_string, "%d", plugin->starting_port); 583 GNUNET_asprintf(&port_as_string, "%d", plugin->port);
604#if DEBUG_UDP_NAT 584#if DEBUG_UDP_NAT
605 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "udp-nat", 585 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "udp-nat",
606 _("Running gnunet-nat-client with arguments: %s %s %d\n"), plugin->external_address, address_as_string, plugin->starting_port); 586 _("Running gnunet-nat-client with arguments: %s %s %d\n"), plugin->external_address, address_as_string, plugin->port);
607#endif 587#endif
608 /* Start the server process */ 588 /* Start the server process */
609 pid = GNUNET_OS_start_process(NULL, NULL, "gnunet-nat-client", "gnunet-nat-client", plugin->external_address, address_as_string, port_as_string, NULL); 589 pid = GNUNET_OS_start_process(NULL, NULL, "gnunet-nat-client", "gnunet-nat-client", plugin->external_address, address_as_string, port_as_string, NULL);
@@ -672,7 +652,7 @@ udp_nat_plugin_send (void *cls,
672 { 652 {
673 /* 653 /*
674 * The first time, we can assume we have no knowledge of a 654 * The first time, we can assume we have no knowledge of a
675 * working port for this peer, call the ICMP message sender 655 * working port for this peer, call the ICMP/UDP message sender
676 * and wait... 656 * and wait...
677 */ 657 */
678 peer_session = GNUNET_malloc(sizeof(struct PeerSession)); 658 peer_session = GNUNET_malloc(sizeof(struct PeerSession));
@@ -700,7 +680,6 @@ udp_nat_plugin_send (void *cls,
700 _("Other peer is NAT'd, set up peer session for peer %s\n"), GNUNET_i2s(target)); 680 _("Other peer is NAT'd, set up peer session for peer %s\n"), GNUNET_i2s(target));
701#endif 681#endif
702 run_gnunet_nat_client(plugin, addr, addrlen); 682 run_gnunet_nat_client(plugin, addr, addrlen);
703
704 } 683 }
705 else 684 else
706 { 685 {
@@ -724,9 +703,12 @@ udp_nat_plugin_send (void *cls,
724 } 703 }
725 else /* Other peer not behind a NAT, so we can just send the message as is */ 704 else /* Other peer not behind a NAT, so we can just send the message as is */
726 { 705 {
727 sent = udp_nat_real_send(cls, udp_nat_socks[0]->desc, target, msgbuf, msgbuf_size, priority, timeout, addr, addrlen, cont, cont_cls); 706 sent = udp_nat_real_send(cls, udp_nat_sock.desc, target, msgbuf, msgbuf_size, priority, timeout, addr, addrlen, cont, cont_cls);
728 } 707 }
729 708
709 if (sent == GNUNET_SYSERR)
710 return 0;
711
730 return sent; 712 return sent;
731} 713}
732 714
@@ -746,13 +728,6 @@ process_interfaces (void *cls,
746 struct sockaddr_in *v4; 728 struct sockaddr_in *v4;
747 struct sockaddr_in6 *v6; 729 struct sockaddr_in6 *v6;
748 730
749 /*
750 * FIXME: Do we want to advertise _all_ of our UDP NAT addresses?
751 * Probably not. Can we assume that we'll only send these out of band?
752 * Ostensibly we won't accept just any connection on these ports anyways
753 * right?
754 */
755
756 af = addr->sa_family; 731 af = addr->sa_family;
757 if (af == AF_INET) 732 if (af == AF_INET)
758 { 733 {
@@ -763,7 +738,7 @@ process_interfaces (void *cls,
763 v4->sin_port = htons (0); /* Indicates to receiver we are behind NAT */ 738 v4->sin_port = htons (0); /* Indicates to receiver we are behind NAT */
764 } 739 }
765 else 740 else
766 v4->sin_port = htons (plugin->starting_port); 741 v4->sin_port = htons (plugin->port);
767 } 742 }
768 else 743 else
769 { 744 {
@@ -772,23 +747,16 @@ process_interfaces (void *cls,
772 if (plugin->behind_nat == GNUNET_YES) 747 if (plugin->behind_nat == GNUNET_YES)
773 v6->sin6_port = htons (0); 748 v6->sin6_port = htons (0);
774 else 749 else
775 v6->sin6_port = htons (plugin->starting_port); 750 v6->sin6_port = htons (plugin->port);
776 } 751 }
777 752
778#if !IPV6 753 GNUNET_log_from (GNUNET_ERROR_TYPE_INFO |
779 if (af == AF_INET) 754 GNUNET_ERROR_TYPE_BULK,
780 { 755 "udp-nat", _("Found address `%s' (%s)\n"),
781#endif 756 GNUNET_a2s (addr, addrlen), name);
782 GNUNET_log_from (GNUNET_ERROR_TYPE_INFO | 757 plugin->env->notify_address (plugin->env->cls,
783 GNUNET_ERROR_TYPE_BULK, 758 "udp_nat",
784 "udp-nat", _("Found address `%s' (%s)\n"), 759 addr, addrlen, GNUNET_TIME_UNIT_FOREVER_REL);
785 GNUNET_a2s (addr, addrlen), name);
786 plugin->env->notify_address (plugin->env->cls,
787 "udp_nat",
788 addr, addrlen, GNUNET_TIME_UNIT_FOREVER_REL);
789#if !IPV6
790 }
791#endif
792 760
793 return GNUNET_OK; 761 return GNUNET_OK;
794} 762}
@@ -835,26 +803,20 @@ send_udp_probe_message (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc
835 message = GNUNET_malloc(sizeof(struct UDP_NAT_ProbeMessage)); 803 message = GNUNET_malloc(sizeof(struct UDP_NAT_ProbeMessage));
836 message->header.size = htons(sizeof(struct UDP_NAT_ProbeMessage)); 804 message->header.size = htons(sizeof(struct UDP_NAT_ProbeMessage));
837 message->header.type = htons(GNUNET_MESSAGE_TYPE_TRANSPORT_UDP_NAT_PROBE); 805 message->header.type = htons(GNUNET_MESSAGE_TYPE_TRANSPORT_UDP_NAT_PROBE);
838 /* Try the agreed upon port first, then go in order starting with our randomly chosen port */ 806 /* If they gave us a port, use that. If not, try our port. */
839 if (probe->index == 0) 807 if (probe->port != 0)
840 { 808 probe->sock_addr.sin_port = htons(probe->port);
841 if (probe->port != 0)
842 probe->sock_addr.sin_port = htons(probe->port);
843 else
844 probe->sock_addr.sin_port = htons(plugin->starting_port);
845 }
846 else 809 else
847 probe->sock_addr.sin_port = htons (GNUNET_CRYPTO_random_u32(GNUNET_CRYPTO_QUALITY_STRONG, 33537) + 32000); /* Find a non-root port */ 810 probe->sock_addr.sin_port = htons(plugin->port);
811
848#if DEBUG_UDP_NAT 812#if DEBUG_UDP_NAT
849 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "udp-nat", 813 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "udp-nat",
850 _("Sending a probe to port %d\n"), ntohs(probe->sock_addr.sin_port)); 814 _("Sending a probe to port %d\n"), ntohs(probe->sock_addr.sin_port));
851#endif 815#endif
852 if (probe->index + 1 < plugin->num_ports)
853 probe->index += 1;
854 else
855 probe->index = 0;
856 816
857 udp_nat_real_send(plugin, udp_nat_socks[probe->index]->desc, NULL, 817 probe->count++;
818
819 udp_nat_real_send(plugin, udp_nat_sock.desc, NULL,
858 (char *)message, ntohs(message->header.size), 0, 820 (char *)message, ntohs(message->header.size), 0,
859 GNUNET_TIME_relative_get_unit(), 821 GNUNET_TIME_relative_get_unit(),
860 &probe->sock_addr, sizeof(probe->sock_addr), 822 &probe->sock_addr, sizeof(probe->sock_addr),
@@ -875,29 +837,20 @@ udp_probe_continuation (void *cls, const struct GNUNET_PeerIdentity *target, int
875 struct UDP_NAT_Probes *probe = cls; 837 struct UDP_NAT_Probes *probe = cls;
876 struct Plugin *plugin = probe->plugin; 838 struct Plugin *plugin = probe->plugin;
877 839
878 if (result == GNUNET_OK) 840 if ((result == GNUNET_OK) && (probe->count < MAX_PROBES))
879 { 841 {
880 if (probe->index == 0)
881 {
882#if DEBUG_UDP_NAT 842#if DEBUG_UDP_NAT
883 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "udp-nat", 843 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "udp-nat",
884 _("Scheduling next probe for 10000 milliseconds\n")); 844 _("Scheduling next probe for 10000 milliseconds\n"));
885#endif 845#endif
886 probe->task = GNUNET_SCHEDULER_add_delayed(plugin->env->sched, GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MILLISECONDS, 10000), &send_udp_probe_message, probe); 846 probe->task = GNUNET_SCHEDULER_add_delayed(plugin->env->sched, GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MILLISECONDS, 10000), &send_udp_probe_message, probe);
887 }
888
889 else
890 {
891 probe->task = GNUNET_SCHEDULER_add_delayed(plugin->env->sched, GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MILLISECONDS, 50), &send_udp_probe_message, probe);
892 }
893 } 847 }
894 else /* Destroy the probe context? */ 848 else /* Destroy the probe context. */
895 { 849 {
896#if DEBUG_UDP_NAT 850#if DEBUG_UDP_NAT
897 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "udp-nat", 851 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "udp-nat",
898 _("Sending probe didn't go well...\n")); 852 _("Sending probe didn't go well...\n"));
899#endif 853#endif
900
901 } 854 }
902} 855}
903 856
@@ -974,7 +927,9 @@ udp_nat_plugin_server_read (void *cls, const struct GNUNET_SCHEDULER_TaskContext
974 _("nat-server-read read: %s port %d\n"), &mybuf, port); 927 _("nat-server-read read: %s port %d\n"), &mybuf, port);
975#endif 928#endif
976 929
977 /* Schedule sending of messages to peer on random ports */ 930 /** We have received an ICMP response, ostensibly from a non-NAT'd peer
931 * that wants to connect to us! Send a message to establish a connection.
932 */
978 temp_probe = find_probe(plugin, &mybuf[0]); 933 temp_probe = find_probe(plugin, &mybuf[0]);
979 934
980 if (temp_probe == NULL) 935 if (temp_probe == NULL)
@@ -983,7 +938,6 @@ udp_nat_plugin_server_read (void *cls, const struct GNUNET_SCHEDULER_TaskContext
983 temp_probe->address_string = strdup(&mybuf[0]); 938 temp_probe->address_string = strdup(&mybuf[0]);
984 temp_probe->sock_addr.sin_family = AF_INET; 939 temp_probe->sock_addr.sin_family = AF_INET;
985 GNUNET_assert(inet_pton(AF_INET, &mybuf[0], &temp_probe->sock_addr.sin_addr) == 1); 940 GNUNET_assert(inet_pton(AF_INET, &mybuf[0], &temp_probe->sock_addr.sin_addr) == 1);
986 temp_probe->index = 0;
987 temp_probe->port = port; 941 temp_probe->port = port;
988 temp_probe->next = plugin->probes; 942 temp_probe->next = plugin->probes;
989 temp_probe->plugin = plugin; 943 temp_probe->plugin = plugin;
@@ -1205,79 +1159,77 @@ udp_nat_plugin_select (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1205 int offset; 1159 int offset;
1206 int count; 1160 int count;
1207 int tsize; 1161 int tsize;
1208 int i; 1162
1209 char *msgbuf; 1163 char *msgbuf;
1210 const struct GNUNET_MessageHeader *currhdr; 1164 const struct GNUNET_MessageHeader *currhdr;
1211 1165
1212 buf = NULL; 1166 buf = NULL;
1213 sender = NULL; 1167 sender = NULL;
1214 1168
1215 for (i = 0; i < plugin->num_ports; i++) 1169 buflen = GNUNET_NETWORK_socket_recvfrom_amount (udp_nat_sock.desc);
1216 {
1217 buflen = GNUNET_NETWORK_socket_recvfrom_amount (udp_nat_socks[i]->desc);
1218 1170
1219 if (buflen == GNUNET_NO) 1171 if (buflen == GNUNET_NO)
1220 continue; 1172 return;
1221 1173
1222 buf = GNUNET_malloc (buflen); 1174 buf = GNUNET_malloc (buflen);
1223 fromlen = sizeof (addr); 1175 fromlen = sizeof (addr);
1224 memset (&addr, 0, fromlen); 1176 memset (&addr, 0, fromlen);
1225 ret = 1177 ret =
1226 GNUNET_NETWORK_socket_recvfrom (udp_nat_socks[i]->desc, buf, buflen, 1178 GNUNET_NETWORK_socket_recvfrom (udp_nat_sock.desc, buf, buflen,
1227 (struct sockaddr *) &addr, &fromlen); 1179 (struct sockaddr *) &addr, &fromlen);
1228 1180
1229#if DEBUG_UDP_NAT 1181#if DEBUG_UDP_NAT
1230 GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, "udp-nat", _ 1182 GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, "udp-nat", _
1231 ("socket_recv returned %u, src_addr_len is %u\n"), ret, 1183 ("socket_recv returned %u, src_addr_len is %u\n"), ret,
1232 fromlen); 1184 fromlen);
1233#endif 1185#endif
1234 1186
1235 if (ret <= 0) 1187 if (ret <= 0)
1236 { 1188 {
1237 GNUNET_free (buf); 1189 GNUNET_free (buf);
1238 continue; 1190 return;
1239 } 1191 }
1240 msg = (struct UDPMessage *) buf; 1192 msg = (struct UDPMessage *) buf;
1241 1193
1242#if DEBUG_UDP_NAT 1194#if DEBUG_UDP_NAT
1243 GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, "udp", _ 1195 GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, "udp", _
1244 ("header reports message size of %d, type %d\n"), 1196 ("header reports message size of %d, type %d\n"),
1245 ntohs (msg->header.size), ntohs (msg->header.type)); 1197 ntohs (msg->header.size), ntohs (msg->header.type));
1246#endif 1198#endif
1247 if (ntohs (msg->header.size) < sizeof (struct UDPMessage)) 1199 if (ntohs (msg->header.size) < sizeof (struct UDPMessage))
1248 { 1200 {
1249 GNUNET_free (buf); 1201 GNUNET_free (buf);
1250 continue; 1202 return;
1251 } 1203 }
1252 1204
1253 msgbuf = (char *)&msg[1]; 1205 msgbuf = (char *)&msg[1];
1254 sender = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity)); 1206 sender = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity));
1255 memcpy (sender, &msg->sender, sizeof (struct GNUNET_PeerIdentity)); 1207 memcpy (sender, &msg->sender, sizeof (struct GNUNET_PeerIdentity));
1256 1208
1257 offset = 0; 1209 offset = 0;
1258 count = 0; 1210 count = 0;
1259 tsize = ntohs (msg->header.size) - sizeof(struct UDPMessage); 1211 tsize = ntohs (msg->header.size) - sizeof(struct UDPMessage);
1260 1212
1261 while (offset < tsize) 1213 while (offset < tsize)
1262 { 1214 {
1263 currhdr = (struct GNUNET_MessageHeader *)&msgbuf[offset]; 1215 currhdr = (struct GNUNET_MessageHeader *)&msgbuf[offset];
1264#if DEBUG_UDP_NAT 1216#if DEBUG_UDP_NAT
1265 GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, "udp", _ 1217 GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, "udp", _
1266 ("processing msg %d: type %d, size %d at offset %d\n"), 1218 ("processing msg %d: type %d, size %d at offset %d\n"),
1267 count, ntohs(currhdr->type), ntohs(currhdr->size), offset); 1219 count, ntohs(currhdr->type), ntohs(currhdr->size), offset);
1268#endif 1220#endif
1269 udp_nat_demultiplexer(plugin, sender, currhdr, &addr, fromlen, udp_nat_socks[i]); 1221 udp_nat_demultiplexer(plugin, sender, currhdr, &addr, fromlen, &udp_nat_sock);
1270#if DEBUG_UDP_NAT 1222#if DEBUG_UDP_NAT
1271 GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, "udp", _ 1223 GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, "udp", _
1272 ("processing done msg %d: type %d, size %d at offset %d\n"), 1224 ("processing done msg %d: type %d, size %d at offset %d\n"),
1273 count, ntohs(currhdr->type), ntohs(currhdr->size), offset); 1225 count, ntohs(currhdr->type), ntohs(currhdr->size), offset);
1274#endif 1226#endif
1275 offset += ntohs(currhdr->size); 1227 offset += ntohs(currhdr->size);
1276 count++; 1228 count++;
1277 }
1278 GNUNET_free_non_null (buf);
1279 GNUNET_free_non_null (sender);
1280 } 1229 }
1230 GNUNET_free_non_null (buf);
1231 GNUNET_free_non_null (sender);
1232
1281 1233
1282 plugin->select_task = 1234 plugin->select_task =
1283 GNUNET_SCHEDULER_add_select (plugin->env->sched, 1235 GNUNET_SCHEDULER_add_select (plugin->env->sched,
@@ -1301,12 +1253,9 @@ udp_nat_transport_server_start (void *cls)
1301{ 1253{
1302 struct Plugin *plugin = cls; 1254 struct Plugin *plugin = cls;
1303 struct sockaddr_in serverAddrv4; 1255 struct sockaddr_in serverAddrv4;
1304#if IPV6
1305 struct sockaddr_in6 serverAddrv6; 1256 struct sockaddr_in6 serverAddrv6;
1306#endif
1307 struct sockaddr *serverAddr; 1257 struct sockaddr *serverAddr;
1308 socklen_t addrlen; 1258 socklen_t addrlen;
1309 int i;
1310 int sockets_created; 1259 int sockets_created;
1311 1260
1312 /* Pipe to read from started processes stdout (on read end) */ 1261 /* Pipe to read from started processes stdout (on read end) */
@@ -1326,7 +1275,14 @@ udp_nat_transport_server_start (void *cls)
1326 /* Start the server process */ 1275 /* Start the server process */
1327 plugin->server_pid = GNUNET_OS_start_process(NULL, plugin->server_stdout, "gnunet-nat-server", "gnunet-nat-server", plugin->internal_address, NULL); 1276 plugin->server_pid = GNUNET_OS_start_process(NULL, plugin->server_stdout, "gnunet-nat-server", "gnunet-nat-server", plugin->internal_address, NULL);
1328 if (plugin->server_pid == GNUNET_SYSERR) 1277 if (plugin->server_pid == GNUNET_SYSERR)
1329 return GNUNET_SYSERR; 1278 {
1279#if DEBUG_UDP_NAT
1280 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG,
1281 "udp_nat",
1282 "Failed to start gnunet-nat-server process\n");
1283#endif
1284 return GNUNET_SYSERR;
1285 }
1330 /* Close the write end of the read pipe */ 1286 /* Close the write end of the read pipe */
1331 GNUNET_DISK_pipe_close_end(plugin->server_stdout, GNUNET_DISK_PIPE_END_WRITE); 1287 GNUNET_DISK_pipe_close_end(plugin->server_stdout, GNUNET_DISK_PIPE_END_WRITE);
1332 1288
@@ -1337,83 +1293,72 @@ udp_nat_transport_server_start (void *cls)
1337 plugin->server_stdout_handle, &udp_nat_plugin_server_read, plugin); 1293 plugin->server_stdout_handle, &udp_nat_plugin_server_read, plugin);
1338 } 1294 }
1339 1295
1340 /* Open all our sockets for reading/writing */ 1296 udp_nat_sock.desc = NULL;
1341 for (i = 0; i < plugin->num_ports; i++) 1297
1342 { 1298
1343 udp_nat_socks[i] = GNUNET_malloc(sizeof(struct UDP_Sock_Info)); 1299 udp_nat_sock.desc = GNUNET_NETWORK_socket_create (PF_INET, SOCK_DGRAM, 17);
1344 udp_nat_socks[i]->desc = NULL; 1300 if (NULL == udp_nat_sock.desc)
1345#if IPV6 1301 {
1346 if (GNUNET_YES != 1302 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "udp-nat", "socket");
1347 GNUNET_CONFIGURATION_get_value_yesno (plugin->env->cfg, "GNUNETD", 1303 return sockets_created;
1348 "DISABLE-IPV6")) 1304 }
1349 { 1305 else
1350 udp_nat_socks[i] = GNUNET_NETWORK_socket_create (PF_INET6, SOCK_DGRAM, 17); 1306 {
1351 if (udp_nat_socks[i] != NULL) 1307 memset (&serverAddrv4, 0, sizeof (serverAddrv4));
1352 { 1308#if HAVE_SOCKADDR_IN_SIN_LEN
1353 memset (&serverAddrv6, 0, sizeof (serverAddrv6)); 1309 serverAddrv4.sin_len = sizeof (serverAddrv4);
1354 #if HAVE_SOCKADDR_IN_SIN_LEN
1355 serverAddrv6.sin6_len = sizeof (serverAddrv6);
1356 #endif
1357 serverAddrv6.sin6_family = AF_INET6;
1358 serverAddrv6.sin6_addr = in6addr_any;
1359 serverAddrv6.sin6_port = htons (i + plugin->starting_port);
1360 addrlen = sizeof (serverAddrv6);
1361 serverAddr = (struct sockaddr *) &serverAddrv6;
1362 }
1363 }
1364#endif 1310#endif
1365 if (NULL == udp_nat_socks[i]->desc) 1311 serverAddrv4.sin_family = AF_INET;
1366 { 1312 serverAddrv4.sin_addr.s_addr = INADDR_ANY;
1367 udp_nat_socks[i]->desc = GNUNET_NETWORK_socket_create (PF_INET, SOCK_DGRAM, 17); 1313 serverAddrv4.sin_port = htons (plugin->port);
1368 if (NULL == udp_nat_socks[i]->desc) 1314 addrlen = sizeof (serverAddrv4);
1369 { 1315 serverAddr = (struct sockaddr *) &serverAddrv4;
1370 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "udp-nat", "socket");
1371 return sockets_created;
1372 }
1373 else
1374 {
1375 memset (&serverAddrv4, 0, sizeof (serverAddrv4));
1376 #if HAVE_SOCKADDR_IN_SIN_LEN
1377 serverAddrv4.sin_len = sizeof (serverAddrv4);
1378 #endif
1379 serverAddrv4.sin_family = AF_INET;
1380 serverAddrv4.sin_addr.s_addr = INADDR_ANY;
1381 if (i == 0)
1382 serverAddrv4.sin_port = htons (plugin->starting_port);
1383 else
1384 serverAddrv4.sin_port = htons (GNUNET_CRYPTO_random_u32(GNUNET_CRYPTO_QUALITY_STRONG, 33537) + 32000); /* Find a non-root port */
1385 addrlen = sizeof (serverAddrv4);
1386 serverAddr = (struct sockaddr *) &serverAddrv4;
1387#if DEBUG_UDP_NAT 1316#if DEBUG_UDP_NAT
1388 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, 1317 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG,
1389 "udp_nat", 1318 "udp_nat",
1390 "Binding to port %d\n", ntohs(serverAddrv4.sin_port)); 1319 "Binding to port %d\n", ntohs(serverAddrv4.sin_port));
1391#endif 1320#endif
1392 while (GNUNET_NETWORK_socket_bind (udp_nat_socks[i]->desc, serverAddr, addrlen) != 1321 while (GNUNET_NETWORK_socket_bind (udp_nat_sock.desc, serverAddr, addrlen) !=
1393 GNUNET_OK) 1322 GNUNET_OK)
1394 { 1323 {
1395 serverAddrv4.sin_port = htons (GNUNET_CRYPTO_random_u32(GNUNET_CRYPTO_QUALITY_STRONG, 33537) + 32000); /* Find a good, non-root port */ 1324 serverAddrv4.sin_port = htons (GNUNET_CRYPTO_random_u32(GNUNET_CRYPTO_QUALITY_STRONG, 33537) + 32000); /* Find a good, non-root port */
1396#if DEBUG_UDP_NAT 1325#if DEBUG_UDP_NAT
1397 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, 1326 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG,
1398 "udp_nat", 1327 "udp_nat",
1399 "Binding failed, trying new port %d\n", ntohs(serverAddrv4.sin_port)); 1328 "Binding failed, trying new port %d\n", ntohs(serverAddrv4.sin_port));
1400#endif 1329#endif
1401 } 1330 }
1402 udp_nat_socks[i]->port = ntohs(serverAddrv4.sin_port); 1331 udp_nat_sock.port = ntohs(serverAddrv4.sin_port);
1403 sockets_created++; 1332 sockets_created++;
1404 } 1333 }
1405 }
1406 1334
1335
1336 if ((udp_nat_sock.desc == NULL) && (GNUNET_YES !=
1337 GNUNET_CONFIGURATION_get_value_yesno (plugin->env->cfg, "GNUNETD",
1338 "DISABLE-IPV6")))
1339 {
1340 udp_nat_sock.desc = GNUNET_NETWORK_socket_create (PF_INET6, SOCK_DGRAM, 17);
1341 if (udp_nat_sock.desc != NULL)
1342 {
1343 memset (&serverAddrv6, 0, sizeof (serverAddrv6));
1344#if HAVE_SOCKADDR_IN_SIN_LEN
1345 serverAddrv6.sin6_len = sizeof (serverAddrv6);
1346#endif
1347 serverAddrv6.sin6_family = AF_INET6;
1348 serverAddrv6.sin6_addr = in6addr_any;
1349 serverAddrv6.sin6_port = htons (plugin->port);
1350 addrlen = sizeof (serverAddrv6);
1351 serverAddr = (struct sockaddr *) &serverAddrv6;
1352 sockets_created++;
1353 }
1407 } 1354 }
1408 1355
1409 plugin->rs = GNUNET_NETWORK_fdset_create (); 1356 plugin->rs = GNUNET_NETWORK_fdset_create ();
1410 1357
1411 GNUNET_NETWORK_fdset_zero (plugin->rs); 1358 GNUNET_NETWORK_fdset_zero (plugin->rs);
1412 1359
1413 for (i = 0; i < plugin->num_ports; i++) 1360
1414 { 1361 GNUNET_NETWORK_fdset_set (plugin->rs, udp_nat_sock.desc);
1415 GNUNET_NETWORK_fdset_set (plugin->rs, udp_nat_socks[i]->desc);
1416 }
1417 1362
1418 plugin->select_task = 1363 plugin->select_task =
1419 GNUNET_SCHEDULER_add_select (plugin->env->sched, 1364 GNUNET_SCHEDULER_add_select (plugin->env->sched,
@@ -1473,15 +1418,10 @@ udp_nat_check_address (void *cls, void *addr, size_t addrlen)
1473 char buf[sizeof (struct sockaddr_in6)]; 1418 char buf[sizeof (struct sockaddr_in6)];
1474 1419
1475 struct sockaddr_in *v4; 1420 struct sockaddr_in *v4;
1476#if IPV6
1477 struct sockaddr_in6 *v6; 1421 struct sockaddr_in6 *v6;
1478#endif 1422
1479#if IPV6
1480 if ((addrlen != sizeof (struct sockaddr_in)) && 1423 if ((addrlen != sizeof (struct sockaddr_in)) &&
1481 (addrlen != sizeof (struct sockaddr_in6))) 1424 (addrlen != sizeof (struct sockaddr_in6)))
1482#else
1483 if (addrlen != sizeof (struct sockaddr_in))
1484#endif
1485 { 1425 {
1486 GNUNET_break_op (0); 1426 GNUNET_break_op (0);
1487 return GNUNET_SYSERR; 1427 return GNUNET_SYSERR;
@@ -1492,13 +1432,12 @@ udp_nat_check_address (void *cls, void *addr, size_t addrlen)
1492 v4 = (struct sockaddr_in *) buf; 1432 v4 = (struct sockaddr_in *) buf;
1493 v4->sin_port = htons (check_port (plugin, ntohs (v4->sin_port))); 1433 v4->sin_port = htons (check_port (plugin, ntohs (v4->sin_port)));
1494 } 1434 }
1495#if IPV6
1496 else 1435 else
1497 { 1436 {
1498 v6 = (struct sockaddr_in6 *) buf; 1437 v6 = (struct sockaddr_in6 *) buf;
1499 v6->sin6_port = htons (check_port (plugin, ntohs (v6->sin6_port))); 1438 v6->sin6_port = htons (check_port (plugin, ntohs (v6->sin6_port)));
1500 } 1439 }
1501#endif 1440
1502#if DEBUG_UDP_NAT 1441#if DEBUG_UDP_NAT
1503 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, 1442 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG,
1504 "udp_nat", 1443 "udp_nat",
@@ -1598,7 +1537,7 @@ libgnunet_plugin_transport_udp_nat_init (void *cls)
1598{ 1537{
1599 struct GNUNET_TRANSPORT_PluginEnvironment *env = cls; 1538 struct GNUNET_TRANSPORT_PluginEnvironment *env = cls;
1600 unsigned long long mtu; 1539 unsigned long long mtu;
1601 unsigned long long starting_port; 1540 unsigned long long port;
1602 struct GNUNET_TRANSPORT_PluginFunctions *api; 1541 struct GNUNET_TRANSPORT_PluginFunctions *api;
1603 struct Plugin *plugin; 1542 struct Plugin *plugin;
1604 struct GNUNET_SERVICE_Context *service; 1543 struct GNUNET_SERVICE_Context *service;
@@ -1647,26 +1586,26 @@ libgnunet_plugin_transport_udp_nat_init (void *cls)
1647 return NULL; 1586 return NULL;
1648 } 1587 }
1649 1588
1650 if (GNUNET_NO == GNUNET_CONFIGURATION_get_value_yesno (env->cfg, 1589 if (GNUNET_YES == GNUNET_CONFIGURATION_get_value_yesno (env->cfg,
1651 "transport-udp-nat", 1590 "transport-udp-nat",
1652 "BEHIND_NAT")) 1591 "BEHIND_NAT"))
1653 behind_nat = GNUNET_NO; /* We are not behind nat, or so says the user! */ 1592 behind_nat = GNUNET_YES; /* We are behind nat (according to the user) */
1654 else 1593 else
1655 behind_nat = GNUNET_YES; /* Assume we are behind nat (default) */ 1594 behind_nat = GNUNET_NO; /* We are not behind nat! */
1656 1595
1657 if (GNUNET_OK != 1596 if (GNUNET_OK !=
1658 GNUNET_CONFIGURATION_get_value_number (env->cfg, 1597 GNUNET_CONFIGURATION_get_value_number (env->cfg,
1659 "transport-udp-nat", 1598 "transport-udp-nat",
1660 "PORT", 1599 "PORT",
1661 &starting_port)) 1600 &port))
1662 starting_port = UDP_NAT_STARTING_PORT; 1601 port = UDP_NAT_DEFAULT_PORT;
1663 else if (starting_port > 65535) 1602 else if (port > 65535)
1664 { 1603 {
1665 GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING, 1604 GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING,
1666 "udp_nat", 1605 "udp_nat",
1667 _("Given `%s' option is out of range: %llu > %u\n"), 1606 _("Given `%s' option is out of range: %llu > %u\n"),
1668 "PORT", 1607 "PORT",
1669 starting_port, 1608 port,
1670 65535); 1609 65535);
1671 GNUNET_SERVICE_stop (service); 1610 GNUNET_SERVICE_stop (service);
1672 GNUNET_free_non_null(external_address); 1611 GNUNET_free_non_null(external_address);
@@ -1684,14 +1623,10 @@ libgnunet_plugin_transport_udp_nat_init (void *cls)
1684 plugin = GNUNET_malloc (sizeof (struct Plugin)); 1623 plugin = GNUNET_malloc (sizeof (struct Plugin));
1685 plugin->external_address = external_address; 1624 plugin->external_address = external_address;
1686 plugin->internal_address = internal_address; 1625 plugin->internal_address = internal_address;
1687 plugin->starting_port = (uint16_t) UDP_NAT_STARTING_PORT; 1626 plugin->port = port;
1688 plugin->behind_nat = behind_nat; 1627 plugin->behind_nat = behind_nat;
1689 if (plugin->behind_nat == GNUNET_NO)
1690 plugin->num_ports = 1; /* Only use one port/socket */
1691 else
1692 plugin->num_ports = UDP_NAT_LISTEN_PORTS;
1693
1694 plugin->env = env; 1628 plugin->env = env;
1629
1695 api = GNUNET_malloc (sizeof (struct GNUNET_TRANSPORT_PluginFunctions)); 1630 api = GNUNET_malloc (sizeof (struct GNUNET_TRANSPORT_PluginFunctions));
1696 api->cls = plugin; 1631 api->cls = plugin;
1697 1632
@@ -1702,10 +1637,6 @@ libgnunet_plugin_transport_udp_nat_init (void *cls)
1702 1637
1703 plugin->service = service; 1638 plugin->service = service;
1704 1639
1705 plugin->random_starting_port = GNUNET_CRYPTO_random_u32(GNUNET_CRYPTO_QUALITY_STRONG, 33537) + 32000;
1706
1707 /* FIXME: do the two calls below periodically again and
1708 not just once (since the info we get might change...) */
1709 GNUNET_OS_network_interfaces_list (&process_interfaces, plugin); 1640 GNUNET_OS_network_interfaces_list (&process_interfaces, plugin);
1710 plugin->hostname_dns = GNUNET_RESOLVER_hostname_resolve (env->sched, 1641 plugin->hostname_dns = GNUNET_RESOLVER_hostname_resolve (env->sched,
1711 env->cfg, 1642 env->cfg,
@@ -1716,7 +1647,7 @@ libgnunet_plugin_transport_udp_nat_init (void *cls)
1716 1647
1717 sockets_created = udp_nat_transport_server_start (plugin); 1648 sockets_created = udp_nat_transport_server_start (plugin);
1718 1649
1719 GNUNET_assert (sockets_created == plugin->num_ports); 1650 GNUNET_assert (sockets_created == 1);
1720 1651
1721 return api; 1652 return api;
1722} 1653}