diff options
author | Nathan S. Evans <evans@in.tum.de> | 2010-06-09 15:32:33 +0000 |
---|---|---|
committer | Nathan S. Evans <evans@in.tum.de> | 2010-06-09 15:32:33 +0000 |
commit | 8346f8d77f92715907e537352abeea84382bd176 (patch) | |
tree | 7be49727db5209ce379bfde5510d98c490176b3c /src | |
parent | 063a4d7093e93ac2d5bcaa3b0b0f3deabbe4f391 (diff) | |
download | gnunet-8346f8d77f92715907e537352abeea84382bd176.tar.gz gnunet-8346f8d77f92715907e537352abeea84382bd176.zip |
first implementation of NAT punching for TCP transport plugin... doubt that it works, but testcases that do NOT use NAT still work. not to be viewed by anyone.
Diffstat (limited to 'src')
-rw-r--r-- | src/transport/plugin_transport_tcp.c | 695 | ||||
-rw-r--r-- | src/transport/plugin_transport_udp.c | 39 | ||||
-rw-r--r-- | src/transport/test_transport_api_tcp_peer1.conf | 1 | ||||
-rw-r--r-- | src/transport/test_transport_api_tcp_peer2.conf | 5 |
4 files changed, 688 insertions, 52 deletions
diff --git a/src/transport/plugin_transport_tcp.c b/src/transport/plugin_transport_tcp.c index f6ba584eb..7fa586588 100644 --- a/src/transport/plugin_transport_tcp.c +++ b/src/transport/plugin_transport_tcp.c | |||
@@ -62,6 +62,50 @@ struct WelcomeMessage | |||
62 | 62 | ||
63 | }; | 63 | }; |
64 | 64 | ||
65 | /** | ||
66 | * Basically a WELCOME message, but with the purpose | ||
67 | * of giving the waiting peer a client handle to use | ||
68 | */ | ||
69 | struct TCP_NAT_ProbeMessage | ||
70 | { | ||
71 | /** | ||
72 | * Type is GNUNET_MESSAGE_TYPE_TRANSPORT_TCP_NAT_PROBE. | ||
73 | */ | ||
74 | struct GNUNET_MessageHeader header; | ||
75 | |||
76 | /** | ||
77 | * Identity of the sender of the message. | ||
78 | */ | ||
79 | struct GNUNET_PeerIdentity clientIdentity; | ||
80 | |||
81 | }; | ||
82 | |||
83 | /** | ||
84 | * Context for sending a NAT probe via TCP. | ||
85 | */ | ||
86 | struct TCPProbeContext | ||
87 | { | ||
88 | /** | ||
89 | * Probe connection. | ||
90 | */ | ||
91 | struct GNUNET_CONNECTION_Handle *sock; | ||
92 | |||
93 | /** | ||
94 | * Message to be sent. | ||
95 | */ | ||
96 | struct TCP_NAT_ProbeMessage message; | ||
97 | |||
98 | /** | ||
99 | * Handle to the transmission. | ||
100 | */ | ||
101 | struct GNUNET_CONNECTION_TransmitHandle *transmit_handle; | ||
102 | |||
103 | /** | ||
104 | * Transport plugin handle. | ||
105 | */ | ||
106 | struct Plugin *plugin; | ||
107 | }; | ||
108 | |||
65 | 109 | ||
66 | /** | 110 | /** |
67 | * Network format for IPv4 addresses. | 111 | * Network format for IPv4 addresses. |
@@ -98,7 +142,6 @@ struct IPv6TcpAddress | |||
98 | 142 | ||
99 | }; | 143 | }; |
100 | 144 | ||
101 | |||
102 | /** | 145 | /** |
103 | * Encapsulation of all of the state of the plugin. | 146 | * Encapsulation of all of the state of the plugin. |
104 | */ | 147 | */ |
@@ -248,6 +291,26 @@ struct Plugin | |||
248 | */ | 291 | */ |
249 | struct GNUNET_CONNECTION_Handle *lsock; | 292 | struct GNUNET_CONNECTION_Handle *lsock; |
250 | 293 | ||
294 | /* | ||
295 | * stdout pipe handle for the gnunet-nat-server process | ||
296 | */ | ||
297 | struct GNUNET_DISK_PipeHandle *server_stdout; | ||
298 | |||
299 | /* | ||
300 | * stdout file handle (for reading) for the gnunet-nat-server process | ||
301 | */ | ||
302 | const struct GNUNET_DISK_FileHandle *server_stdout_handle; | ||
303 | |||
304 | /** | ||
305 | * ID of select gnunet-nat-server stdout read task | ||
306 | */ | ||
307 | GNUNET_SCHEDULER_TaskIdentifier server_read_task; | ||
308 | |||
309 | /** | ||
310 | * The process id of the server process (if behind NAT) | ||
311 | */ | ||
312 | pid_t server_pid; | ||
313 | |||
251 | /** | 314 | /** |
252 | * List of open TCP sessions. | 315 | * List of open TCP sessions. |
253 | */ | 316 | */ |
@@ -275,6 +338,22 @@ struct Plugin | |||
275 | struct GNUNET_RESOLVER_RequestHandle *hostname_dns; | 338 | struct GNUNET_RESOLVER_RequestHandle *hostname_dns; |
276 | 339 | ||
277 | /** | 340 | /** |
341 | * Map of peers we have tried to contact behind a NAT | ||
342 | */ | ||
343 | struct GNUNET_CONTAINER_MultiHashMap *nat_wait_conns; | ||
344 | |||
345 | /** | ||
346 | * The external address given to us by the user. Must be actual | ||
347 | * outside visible address for NAT punching to work. | ||
348 | */ | ||
349 | char *external_address; | ||
350 | |||
351 | /** | ||
352 | * The internal address given to us by the user (or discovered). | ||
353 | */ | ||
354 | char *internal_address; | ||
355 | |||
356 | /** | ||
278 | * ID of task used to update our addresses when one expires. | 357 | * ID of task used to update our addresses when one expires. |
279 | */ | 358 | */ |
280 | GNUNET_SCHEDULER_TaskIdentifier address_update_task; | 359 | GNUNET_SCHEDULER_TaskIdentifier address_update_task; |
@@ -290,6 +369,16 @@ struct Plugin | |||
290 | */ | 369 | */ |
291 | uint16_t adv_port; | 370 | uint16_t adv_port; |
292 | 371 | ||
372 | /** | ||
373 | * Is this transport configured to be behind a NAT? | ||
374 | */ | ||
375 | int behind_nat; | ||
376 | |||
377 | /** | ||
378 | * Is this transport configured to allow connections to NAT'd peers? | ||
379 | */ | ||
380 | int allow_nat; | ||
381 | |||
293 | }; | 382 | }; |
294 | 383 | ||
295 | 384 | ||
@@ -373,25 +462,31 @@ find_session_by_client (struct Plugin *plugin, | |||
373 | return ret; | 462 | return ret; |
374 | } | 463 | } |
375 | 464 | ||
376 | |||
377 | /** | 465 | /** |
378 | * Create a new session. Also queues a welcome message. | 466 | * Create a new session. Also queues a welcome message. |
379 | * | 467 | * |
380 | * @param plugin us | 468 | * @param plugin us |
381 | * @param target peer to connect to | 469 | * @param target peer to connect to |
382 | * @param client client to use | 470 | * @param client client to use |
471 | * @param is_nat this a NAT session, we should wait for a client to | ||
472 | * connect to us from an address, then assign that to | ||
473 | * the session | ||
383 | * @return new session object | 474 | * @return new session object |
384 | */ | 475 | */ |
385 | static struct Session * | 476 | static struct Session * |
386 | create_session (struct Plugin *plugin, | 477 | create_session (struct Plugin *plugin, |
387 | const struct GNUNET_PeerIdentity *target, | 478 | const struct GNUNET_PeerIdentity *target, |
388 | struct GNUNET_SERVER_Client *client) | 479 | struct GNUNET_SERVER_Client *client, int is_nat) |
389 | { | 480 | { |
390 | struct Session *ret; | 481 | struct Session *ret; |
391 | struct PendingMessage *pm; | 482 | struct PendingMessage *pm; |
392 | struct WelcomeMessage welcome; | 483 | struct WelcomeMessage welcome; |
393 | 484 | ||
394 | GNUNET_assert (client != NULL); | 485 | if (is_nat != GNUNET_YES) |
486 | GNUNET_assert (client != NULL); | ||
487 | else | ||
488 | GNUNET_assert (client == NULL); | ||
489 | |||
395 | #if DEBUG_TCP | 490 | #if DEBUG_TCP |
396 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, | 491 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, |
397 | "tcp", | 492 | "tcp", |
@@ -401,8 +496,11 @@ create_session (struct Plugin *plugin, | |||
401 | ret = GNUNET_malloc (sizeof (struct Session)); | 496 | ret = GNUNET_malloc (sizeof (struct Session)); |
402 | ret->last_activity = GNUNET_TIME_absolute_get (); | 497 | ret->last_activity = GNUNET_TIME_absolute_get (); |
403 | ret->plugin = plugin; | 498 | ret->plugin = plugin; |
404 | ret->next = plugin->sessions; | 499 | if (is_nat != GNUNET_YES) /* If not a NAT WAIT conn, add it to global list */ |
405 | plugin->sessions = ret; | 500 | { |
501 | ret->next = plugin->sessions; | ||
502 | plugin->sessions = ret; | ||
503 | } | ||
406 | ret->client = client; | 504 | ret->client = client; |
407 | ret->target = *target; | 505 | ret->target = *target; |
408 | ret->expecting_welcome = GNUNET_YES; | 506 | ret->expecting_welcome = GNUNET_YES; |
@@ -421,10 +519,11 @@ create_session (struct Plugin *plugin, | |||
421 | GNUNET_CONTAINER_DLL_insert (ret->pending_messages_head, | 519 | GNUNET_CONTAINER_DLL_insert (ret->pending_messages_head, |
422 | ret->pending_messages_tail, | 520 | ret->pending_messages_tail, |
423 | pm); | 521 | pm); |
424 | GNUNET_STATISTICS_update (plugin->env->stats, | 522 | if (is_nat != GNUNET_YES) |
425 | gettext_noop ("# TCP sessions active"), | 523 | GNUNET_STATISTICS_update (plugin->env->stats, |
426 | 1, | 524 | gettext_noop ("# TCP sessions active"), |
427 | GNUNET_NO); | 525 | 1, |
526 | GNUNET_NO); | ||
428 | return ret; | 527 | return ret; |
429 | } | 528 | } |
430 | 529 | ||
@@ -724,6 +823,54 @@ select_better_session (struct Session *s1, | |||
724 | 823 | ||
725 | 824 | ||
726 | /** | 825 | /** |
826 | * We learned about a peer (possibly behind NAT) so run the | ||
827 | * gnunet-nat-client to send dummy ICMP responses | ||
828 | * | ||
829 | * @param plugin the plugin for this transport | ||
830 | * @param addr the address of the peer | ||
831 | * @param addrlen the length of the address | ||
832 | */ | ||
833 | void | ||
834 | run_gnunet_nat_client (struct Plugin *plugin, const char *addr, size_t addrlen) | ||
835 | { | ||
836 | char inet4[INET_ADDRSTRLEN]; | ||
837 | char *address_as_string; | ||
838 | char *port_as_string; | ||
839 | pid_t pid; | ||
840 | const struct sockaddr *sa = (const struct sockaddr *)addr; | ||
841 | |||
842 | if (addrlen < sizeof (struct sockaddr)) | ||
843 | return; | ||
844 | switch (sa->sa_family) | ||
845 | { | ||
846 | case AF_INET: | ||
847 | if (addrlen != sizeof (struct sockaddr_in)) | ||
848 | return; | ||
849 | inet_ntop (AF_INET, | ||
850 | &((struct sockaddr_in *) sa)->sin_addr, | ||
851 | inet4, INET_ADDRSTRLEN); | ||
852 | address_as_string = GNUNET_strdup (inet4); | ||
853 | break; | ||
854 | case AF_INET6: | ||
855 | default: | ||
856 | return; | ||
857 | } | ||
858 | |||
859 | GNUNET_asprintf(&port_as_string, "%d", plugin->adv_port); | ||
860 | #if DEBUG_UDP_NAT | ||
861 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "tcp", | ||
862 | _("Running gnunet-nat-client with arguments: %s %s %d\n"), plugin->external_address, address_as_string, plugin->adv_port); | ||
863 | #endif | ||
864 | |||
865 | /* Start the client process */ | ||
866 | pid = GNUNET_OS_start_process(NULL, NULL, "gnunet-nat-client", "gnunet-nat-client", plugin->external_address, address_as_string, port_as_string, NULL); | ||
867 | GNUNET_free(address_as_string); | ||
868 | GNUNET_free(port_as_string); | ||
869 | GNUNET_OS_process_wait (pid); | ||
870 | } | ||
871 | |||
872 | |||
873 | /** | ||
727 | * Function that can be used by the transport service to transmit | 874 | * Function that can be used by the transport service to transmit |
728 | * a message using the plugin. Note that in the case of a | 875 | * a message using the plugin. Note that in the case of a |
729 | * peer disconnecting, the continuation MUST be called | 876 | * peer disconnecting, the continuation MUST be called |
@@ -757,7 +904,7 @@ select_better_session (struct Session *s1, | |||
757 | * @param cont_cls closure for cont | 904 | * @param cont_cls closure for cont |
758 | * @return number of bytes used (on the physical network, with overheads); | 905 | * @return number of bytes used (on the physical network, with overheads); |
759 | * -1 on hard errors (i.e. address invalid); 0 is a legal value | 906 | * -1 on hard errors (i.e. address invalid); 0 is a legal value |
760 | * and does NOT mean that the message was not transmitted (DV) | 907 | * and does NOT mean that the message was not transmitted (DV and NAT) |
761 | */ | 908 | */ |
762 | static ssize_t | 909 | static ssize_t |
763 | tcp_plugin_send (void *cls, | 910 | tcp_plugin_send (void *cls, |
@@ -784,6 +931,7 @@ tcp_plugin_send (void *cls, | |||
784 | struct sockaddr_in6 a6; | 931 | struct sockaddr_in6 a6; |
785 | const struct IPv4TcpAddress *t4; | 932 | const struct IPv4TcpAddress *t4; |
786 | const struct IPv6TcpAddress *t6; | 933 | const struct IPv6TcpAddress *t6; |
934 | unsigned int is_natd; | ||
787 | 935 | ||
788 | GNUNET_STATISTICS_update (plugin->env->stats, | 936 | GNUNET_STATISTICS_update (plugin->env->stats, |
789 | gettext_noop ("# bytes TCP was asked to transmit"), | 937 | gettext_noop ("# bytes TCP was asked to transmit"), |
@@ -792,6 +940,7 @@ tcp_plugin_send (void *cls, | |||
792 | /* FIXME: we could do this cheaper with a hash table | 940 | /* FIXME: we could do this cheaper with a hash table |
793 | where we could restrict the iteration to entries that match | 941 | where we could restrict the iteration to entries that match |
794 | the target peer... */ | 942 | the target peer... */ |
943 | is_natd = GNUNET_NO; | ||
795 | if (session == NULL) | 944 | if (session == NULL) |
796 | { | 945 | { |
797 | cand_session = NULL; | 946 | cand_session = NULL; |
@@ -860,6 +1009,8 @@ tcp_plugin_send (void *cls, | |||
860 | #endif | 1009 | #endif |
861 | a6.sin6_family = AF_INET6; | 1010 | a6.sin6_family = AF_INET6; |
862 | a6.sin6_port = t6->t6_port; | 1011 | a6.sin6_port = t6->t6_port; |
1012 | if (t6->t6_port == 0) | ||
1013 | is_natd = GNUNET_YES; | ||
863 | memcpy (&a6.sin6_addr, | 1014 | memcpy (&a6.sin6_addr, |
864 | &t6->ipv6_addr, | 1015 | &t6->ipv6_addr, |
865 | sizeof (struct in6_addr)); | 1016 | sizeof (struct in6_addr)); |
@@ -876,6 +1027,8 @@ tcp_plugin_send (void *cls, | |||
876 | #endif | 1027 | #endif |
877 | a4.sin_family = AF_INET; | 1028 | a4.sin_family = AF_INET; |
878 | a4.sin_port = t4->t_port; | 1029 | a4.sin_port = t4->t_port; |
1030 | if (t4->t_port == 0) | ||
1031 | is_natd = GNUNET_YES; | ||
879 | a4.sin_addr.s_addr = t4->ipv4_addr; | 1032 | a4.sin_addr.s_addr = t4->ipv4_addr; |
880 | sb = &a4; | 1033 | sb = &a4; |
881 | sbs = sizeof (a4); | 1034 | sbs = sizeof (a4); |
@@ -889,6 +1042,47 @@ tcp_plugin_send (void *cls, | |||
889 | GNUNET_break (0); | 1042 | GNUNET_break (0); |
890 | return -1; | 1043 | return -1; |
891 | } | 1044 | } |
1045 | |||
1046 | if ((is_natd == GNUNET_YES) && (addrlen == sizeof (struct IPv6TcpAddress))) | ||
1047 | return -1; /* NAT client only works with IPv4 addresses */ | ||
1048 | |||
1049 | if ( (plugin->allow_nat == GNUNET_YES) && (is_natd == GNUNET_YES) && | ||
1050 | (GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains(plugin->nat_wait_conns, &target->hashPubKey))) | ||
1051 | { | ||
1052 | session = create_session (plugin, | ||
1053 | target, | ||
1054 | NULL, is_natd); | ||
1055 | |||
1056 | /* create new message entry */ | ||
1057 | pm = GNUNET_malloc (sizeof (struct PendingMessage) + msgbuf_size); | ||
1058 | pm->msg = (const char*) &pm[1]; | ||
1059 | memcpy (&pm[1], msg, msgbuf_size); | ||
1060 | pm->message_size = msgbuf_size; | ||
1061 | pm->timeout = GNUNET_TIME_relative_to_absolute (timeout); | ||
1062 | pm->transmit_cont = cont; | ||
1063 | pm->transmit_cont_cls = cont_cls; | ||
1064 | |||
1065 | /* append pm to pending_messages list */ | ||
1066 | GNUNET_CONTAINER_DLL_insert_after (session->pending_messages_head, | ||
1067 | session->pending_messages_tail, | ||
1068 | session->pending_messages_tail, | ||
1069 | pm); | ||
1070 | |||
1071 | GNUNET_CONTAINER_multihashmap_put(plugin->nat_wait_conns, &target->hashPubKey, session, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY); | ||
1072 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, | ||
1073 | "tcp", | ||
1074 | "Created NAT WAIT connection to `%4s' at `%s'\n", | ||
1075 | GNUNET_i2s (target), | ||
1076 | GNUNET_a2s (sb, sbs)); | ||
1077 | |||
1078 | run_gnunet_nat_client(plugin, addr, addrlen); | ||
1079 | return 0; | ||
1080 | } | ||
1081 | else if ((plugin->allow_nat == GNUNET_YES) && (is_natd == GNUNET_YES) && (GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains(plugin->nat_wait_conns, &target->hashPubKey))) | ||
1082 | { | ||
1083 | /* Only do one NAT punch attempt per peer identity */ | ||
1084 | return -1; | ||
1085 | } | ||
892 | sa = GNUNET_CONNECTION_create_from_sockaddr (plugin->env->sched, | 1086 | sa = GNUNET_CONNECTION_create_from_sockaddr (plugin->env->sched, |
893 | af, sb, sbs, | 1087 | af, sb, sbs, |
894 | GNUNET_SERVER_MAX_MESSAGE_SIZE); | 1088 | GNUNET_SERVER_MAX_MESSAGE_SIZE); |
@@ -917,7 +1111,7 @@ tcp_plugin_send (void *cls, | |||
917 | session = create_session (plugin, | 1111 | session = create_session (plugin, |
918 | target, | 1112 | target, |
919 | GNUNET_SERVER_connect_socket (plugin->server, | 1113 | GNUNET_SERVER_connect_socket (plugin->server, |
920 | sa)); | 1114 | sa), is_natd); |
921 | session->connect_addr = GNUNET_malloc (addrlen); | 1115 | session->connect_addr = GNUNET_malloc (addrlen); |
922 | memcpy (session->connect_addr, | 1116 | memcpy (session->connect_addr, |
923 | addr, | 1117 | addr, |
@@ -1194,6 +1388,107 @@ tcp_plugin_check_address (void *cls, void *addr, size_t addrlen) | |||
1194 | return GNUNET_OK; | 1388 | return GNUNET_OK; |
1195 | } | 1389 | } |
1196 | 1390 | ||
1391 | /** | ||
1392 | * We've received a nat probe from this peer via TCP. Finish | ||
1393 | * creating the client session and resume sending of queued | ||
1394 | * messages. | ||
1395 | * | ||
1396 | * @param cls closure | ||
1397 | * @param client identification of the client | ||
1398 | * @param message the actual message | ||
1399 | */ | ||
1400 | static void | ||
1401 | handle_tcp_nat_probe (void *cls, | ||
1402 | struct GNUNET_SERVER_Client *client, | ||
1403 | const struct GNUNET_MessageHeader *message) | ||
1404 | { | ||
1405 | struct Plugin *plugin = cls; | ||
1406 | struct Session *session; | ||
1407 | struct TCP_NAT_ProbeMessage *tcp_nat_probe; | ||
1408 | size_t alen; | ||
1409 | void *vaddr; | ||
1410 | struct IPv4TcpAddress *t4; | ||
1411 | struct IPv6TcpAddress *t6; | ||
1412 | const struct sockaddr_in *s4; | ||
1413 | const struct sockaddr_in6 *s6; | ||
1414 | |||
1415 | /* We have received a TCP NAT probe, meaning we (hopefully) initiated | ||
1416 | * a connection to this peer by running gnunet-nat-client. This peer | ||
1417 | * received the punch message and now wants us to use the new connection | ||
1418 | * as the default for that peer. Do so and then send a WELCOME message | ||
1419 | * so we can really be connected! | ||
1420 | */ | ||
1421 | if (ntohs(message->size) != sizeof(struct TCP_NAT_ProbeMessage)) | ||
1422 | { | ||
1423 | GNUNET_break_op(0); | ||
1424 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | ||
1425 | return; | ||
1426 | } | ||
1427 | tcp_nat_probe = (struct TCP_NAT_ProbeMessage *)message; | ||
1428 | |||
1429 | if (GNUNET_CONTAINER_multihashmap_contains(plugin->nat_wait_conns, &tcp_nat_probe->clientIdentity.hashPubKey) == GNUNET_YES) | ||
1430 | { | ||
1431 | session = GNUNET_CONTAINER_multihashmap_get(plugin->nat_wait_conns, &tcp_nat_probe->clientIdentity.hashPubKey); | ||
1432 | GNUNET_assert(session != NULL); | ||
1433 | GNUNET_SERVER_client_keep (client); | ||
1434 | session->client = client; | ||
1435 | |||
1436 | if (GNUNET_OK == | ||
1437 | GNUNET_SERVER_client_get_address (client, &vaddr, &alen)) | ||
1438 | { | ||
1439 | #if DEBUG_TCP | ||
1440 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, | ||
1441 | "tcp", | ||
1442 | "Found address `%s' for incoming connection %p\n", | ||
1443 | GNUNET_a2s (vaddr, alen), | ||
1444 | client); | ||
1445 | #endif | ||
1446 | if (alen == sizeof (struct sockaddr_in)) | ||
1447 | { | ||
1448 | s4 = vaddr; | ||
1449 | t4 = GNUNET_malloc (sizeof (struct IPv4TcpAddress)); | ||
1450 | t4->t_port = s4->sin_port; | ||
1451 | t4->ipv4_addr = s4->sin_addr.s_addr; | ||
1452 | session->connect_addr = t4; | ||
1453 | session->connect_alen = sizeof (struct IPv4TcpAddress); | ||
1454 | } | ||
1455 | else if (alen == sizeof (struct sockaddr_in6)) | ||
1456 | { | ||
1457 | s6 = vaddr; | ||
1458 | t6 = GNUNET_malloc (sizeof (struct IPv6TcpAddress)); | ||
1459 | t6->t6_port = s6->sin6_port; | ||
1460 | memcpy (&t6->ipv6_addr, | ||
1461 | &s6->sin6_addr, | ||
1462 | sizeof (struct in6_addr)); | ||
1463 | session->connect_addr = t6; | ||
1464 | session->connect_alen = sizeof (struct IPv6TcpAddress); | ||
1465 | } | ||
1466 | |||
1467 | session->connect_addr = GNUNET_malloc (alen); | ||
1468 | memcpy (session->connect_addr, | ||
1469 | vaddr, | ||
1470 | alen); | ||
1471 | session->connect_alen = alen; | ||
1472 | GNUNET_free (vaddr); | ||
1473 | } | ||
1474 | else | ||
1475 | { | ||
1476 | /* FIXME: free partial session? */ | ||
1477 | } | ||
1478 | |||
1479 | |||
1480 | session->next = plugin->sessions; | ||
1481 | plugin->sessions = session; | ||
1482 | |||
1483 | GNUNET_STATISTICS_update (plugin->env->stats, | ||
1484 | gettext_noop ("# TCP sessions active"), | ||
1485 | 1, | ||
1486 | GNUNET_NO); | ||
1487 | /*GNUNET_SERVER_connect_socket (plugin->server, | ||
1488 | client);*/ | ||
1489 | } | ||
1490 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | ||
1491 | } | ||
1197 | 1492 | ||
1198 | /** | 1493 | /** |
1199 | * We've received a welcome from this peer via TCP. Possibly create a | 1494 | * We've received a welcome from this peer via TCP. Possibly create a |
@@ -1235,7 +1530,7 @@ handle_tcp_welcome (void *cls, | |||
1235 | { | 1530 | { |
1236 | GNUNET_SERVER_client_keep (client); | 1531 | GNUNET_SERVER_client_keep (client); |
1237 | session = create_session (plugin, | 1532 | session = create_session (plugin, |
1238 | &wm->clientIdentity, client); | 1533 | &wm->clientIdentity, client, GNUNET_NO); |
1239 | session->inbound = GNUNET_YES; | 1534 | session->inbound = GNUNET_YES; |
1240 | if (GNUNET_OK == | 1535 | if (GNUNET_OK == |
1241 | GNUNET_SERVER_client_get_address (client, &vaddr, &alen)) | 1536 | GNUNET_SERVER_client_get_address (client, &vaddr, &alen)) |
@@ -1342,14 +1637,14 @@ handle_tcp_data (void *cls, | |||
1342 | struct Session *session; | 1637 | struct Session *session; |
1343 | struct GNUNET_TIME_Relative delay; | 1638 | struct GNUNET_TIME_Relative delay; |
1344 | 1639 | ||
1345 | if (GNUNET_MESSAGE_TYPE_TRANSPORT_TCP_WELCOME == ntohs(message->type)) | 1640 | if ((GNUNET_MESSAGE_TYPE_TRANSPORT_TCP_WELCOME == ntohs(message->type)) || (ntohs(message->type) == GNUNET_MESSAGE_TYPE_TRANSPORT_TCP_NAT_PROBE)) |
1346 | { | 1641 | { |
1347 | /* We don't want to propagate WELCOME messages up! */ | 1642 | /* We don't want to propagate WELCOME messages up! */ |
1348 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | 1643 | GNUNET_SERVER_receive_done (client, GNUNET_OK); |
1349 | return; | 1644 | return; |
1350 | } | 1645 | } |
1351 | session = find_session_by_client (plugin, client); | 1646 | session = find_session_by_client (plugin, client); |
1352 | if ( (NULL == session) || (GNUNET_NO != session->expecting_welcome)) | 1647 | if ( (NULL == session) || (GNUNET_YES == session->expecting_welcome)) |
1353 | { | 1648 | { |
1354 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); | 1649 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); |
1355 | return; | 1650 | return; |
@@ -1386,6 +1681,7 @@ handle_tcp_data (void *cls, | |||
1386 | static struct GNUNET_SERVER_MessageHandler my_handlers[] = { | 1681 | static struct GNUNET_SERVER_MessageHandler my_handlers[] = { |
1387 | {&handle_tcp_welcome, NULL, GNUNET_MESSAGE_TYPE_TRANSPORT_TCP_WELCOME, | 1682 | {&handle_tcp_welcome, NULL, GNUNET_MESSAGE_TYPE_TRANSPORT_TCP_WELCOME, |
1388 | sizeof (struct WelcomeMessage)}, | 1683 | sizeof (struct WelcomeMessage)}, |
1684 | {&handle_tcp_nat_probe, NULL, GNUNET_MESSAGE_TYPE_TRANSPORT_TCP_NAT_PROBE, sizeof (struct TCP_NAT_ProbeMessage)}, | ||
1389 | {&handle_tcp_data, NULL, GNUNET_MESSAGE_TYPE_ALL, 0}, | 1685 | {&handle_tcp_data, NULL, GNUNET_MESSAGE_TYPE_ALL, 0}, |
1390 | {NULL, NULL, 0, 0} | 1686 | {NULL, NULL, 0, 0} |
1391 | }; | 1687 | }; |
@@ -1453,7 +1749,10 @@ process_interfaces (void *cls, | |||
1453 | if (af == AF_INET) | 1749 | if (af == AF_INET) |
1454 | { | 1750 | { |
1455 | t4.ipv4_addr = ((struct sockaddr_in *) addr)->sin_addr.s_addr; | 1751 | t4.ipv4_addr = ((struct sockaddr_in *) addr)->sin_addr.s_addr; |
1456 | t4.t_port = htons (plugin->adv_port); | 1752 | if (plugin->behind_nat) |
1753 | t4.t_port = htons(0); | ||
1754 | else | ||
1755 | t4.t_port = htons (plugin->adv_port); | ||
1457 | arg = &t4; | 1756 | arg = &t4; |
1458 | args = sizeof (t4); | 1757 | args = sizeof (t4); |
1459 | } | 1758 | } |
@@ -1467,7 +1766,10 @@ process_interfaces (void *cls, | |||
1467 | memcpy (&t6.ipv6_addr, | 1766 | memcpy (&t6.ipv6_addr, |
1468 | &((struct sockaddr_in6 *) addr)->sin6_addr, | 1767 | &((struct sockaddr_in6 *) addr)->sin6_addr, |
1469 | sizeof (struct in6_addr)); | 1768 | sizeof (struct in6_addr)); |
1470 | t6.t6_port = htons (plugin->adv_port); | 1769 | if (plugin->behind_nat) |
1770 | t6.t6_port = htons(0); | ||
1771 | else | ||
1772 | t6.t6_port = htons (plugin->adv_port); | ||
1471 | arg = &t6; | 1773 | arg = &t6; |
1472 | args = sizeof (t6); | 1774 | args = sizeof (t6); |
1473 | } | 1775 | } |
@@ -1508,9 +1810,267 @@ process_hostname_ips (void *cls, | |||
1508 | plugin->hostname_dns = NULL; | 1810 | plugin->hostname_dns = NULL; |
1509 | return; | 1811 | return; |
1510 | } | 1812 | } |
1813 | /* FIXME: Can we figure out our external address here so it doesn't need to be user specified? */ | ||
1511 | process_interfaces (plugin, "<hostname>", GNUNET_YES, addr, addrlen); | 1814 | process_interfaces (plugin, "<hostname>", GNUNET_YES, addr, addrlen); |
1512 | } | 1815 | } |
1513 | 1816 | ||
1817 | /** | ||
1818 | * We can now send a probe message, copy into buffer to really send. | ||
1819 | * | ||
1820 | * @param cls closure, a struct TCPProbeContext | ||
1821 | * @param size max size to copy | ||
1822 | * @param buf buffer to copy message to | ||
1823 | */ | ||
1824 | static size_t notify_send_probe (void *cls, | ||
1825 | size_t size, void *buf) | ||
1826 | { | ||
1827 | struct TCPProbeContext *tcp_probe_ctx = cls; | ||
1828 | |||
1829 | if (buf == NULL) | ||
1830 | { | ||
1831 | return 0; | ||
1832 | } | ||
1833 | |||
1834 | GNUNET_assert(size >= sizeof(tcp_probe_ctx->message)); | ||
1835 | memcpy(buf, &tcp_probe_ctx->message, sizeof(tcp_probe_ctx->message)); | ||
1836 | GNUNET_SERVER_connect_socket (tcp_probe_ctx->plugin->server, | ||
1837 | tcp_probe_ctx->sock); | ||
1838 | |||
1839 | GNUNET_free(tcp_probe_ctx); | ||
1840 | return sizeof(tcp_probe_ctx->message); | ||
1841 | } | ||
1842 | |||
1843 | /* | ||
1844 | * @param cls the plugin handle | ||
1845 | * @param tc the scheduling context (for rescheduling this function again) | ||
1846 | * | ||
1847 | * We have been notified that gnunet-nat-server has written something to stdout. | ||
1848 | * Handle the output, then reschedule this function to be called again once | ||
1849 | * more is available. | ||
1850 | * | ||
1851 | */ | ||
1852 | static void | ||
1853 | tcp_plugin_server_read (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
1854 | { | ||
1855 | struct Plugin *plugin = cls; | ||
1856 | char mybuf[40]; | ||
1857 | ssize_t bytes; | ||
1858 | memset(&mybuf, 0, sizeof(mybuf)); | ||
1859 | int i; | ||
1860 | int port; | ||
1861 | char *port_start; | ||
1862 | struct sockaddr_in in_addr; | ||
1863 | struct TCPProbeContext *tcp_probe_ctx; | ||
1864 | struct GNUNET_CONNECTION_Handle *sock; | ||
1865 | |||
1866 | if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN) | ||
1867 | return; | ||
1868 | |||
1869 | bytes = GNUNET_DISK_file_read(plugin->server_stdout_handle, &mybuf, sizeof(mybuf)); | ||
1870 | |||
1871 | if (bytes < 1) | ||
1872 | { | ||
1873 | #if DEBUG_UDP_NAT | ||
1874 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "tcp", | ||
1875 | _("Finished reading from server stdout with code: %d\n"), bytes); | ||
1876 | #endif | ||
1877 | return; | ||
1878 | } | ||
1879 | |||
1880 | port = 0; | ||
1881 | port_start = NULL; | ||
1882 | for (i = 0; i < sizeof(mybuf); i++) | ||
1883 | { | ||
1884 | if (mybuf[i] == '\n') | ||
1885 | mybuf[i] = '\0'; | ||
1886 | |||
1887 | if ((mybuf[i] == ':') && (i + 1 < sizeof(mybuf))) | ||
1888 | { | ||
1889 | mybuf[i] = '\0'; | ||
1890 | port_start = &mybuf[i + 1]; | ||
1891 | } | ||
1892 | } | ||
1893 | |||
1894 | if (port_start != NULL) | ||
1895 | port = atoi(port_start); | ||
1896 | else | ||
1897 | { | ||
1898 | plugin->server_read_task = | ||
1899 | GNUNET_SCHEDULER_add_read_file (plugin->env->sched, | ||
1900 | GNUNET_TIME_UNIT_FOREVER_REL, | ||
1901 | plugin->server_stdout_handle, &tcp_plugin_server_read, plugin); | ||
1902 | return; | ||
1903 | } | ||
1904 | |||
1905 | #if DEBUG_UDP_NAT | ||
1906 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "tcp", | ||
1907 | _("nat-server-read read: %s port %d\n"), &mybuf, port); | ||
1908 | #endif | ||
1909 | |||
1910 | |||
1911 | if (inet_pton(AF_INET, &mybuf[0], &in_addr.sin_addr) != 1) | ||
1912 | { | ||
1913 | |||
1914 | GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING, "tcp", | ||
1915 | _("nat-server-read malformed address\n"), &mybuf, port); | ||
1916 | |||
1917 | plugin->server_read_task = | ||
1918 | GNUNET_SCHEDULER_add_read_file (plugin->env->sched, | ||
1919 | GNUNET_TIME_UNIT_FOREVER_REL, | ||
1920 | plugin->server_stdout_handle, &tcp_plugin_server_read, plugin); | ||
1921 | return; | ||
1922 | } | ||
1923 | |||
1924 | /** | ||
1925 | * We have received an ICMP response, ostensibly from a non-NAT'd peer | ||
1926 | * that wants to connect to us! Send a message to establish a connection. | ||
1927 | */ | ||
1928 | sock = GNUNET_CONNECTION_create_from_sockaddr (plugin->env->sched, AF_INET, (struct sockaddr *)&in_addr, | ||
1929 | sizeof(in_addr), GNUNET_SERVER_MAX_MESSAGE_SIZE); | ||
1930 | |||
1931 | if (sock == NULL) | ||
1932 | { | ||
1933 | plugin->server_read_task = | ||
1934 | GNUNET_SCHEDULER_add_read_file (plugin->env->sched, | ||
1935 | GNUNET_TIME_UNIT_FOREVER_REL, | ||
1936 | plugin->server_stdout_handle, &tcp_plugin_server_read, plugin); | ||
1937 | return; | ||
1938 | } | ||
1939 | else | ||
1940 | { | ||
1941 | tcp_probe_ctx = GNUNET_malloc(sizeof(struct TCPProbeContext)); | ||
1942 | |||
1943 | tcp_probe_ctx->message.header.size = htons(sizeof(struct TCP_NAT_ProbeMessage)); | ||
1944 | tcp_probe_ctx->message.header.type = htons(GNUNET_MESSAGE_TYPE_TRANSPORT_TCP_NAT_PROBE); | ||
1945 | memcpy(&tcp_probe_ctx->message.clientIdentity, plugin->env->my_identity, sizeof(struct GNUNET_PeerIdentity)); | ||
1946 | tcp_probe_ctx->plugin = plugin; | ||
1947 | |||
1948 | tcp_probe_ctx->transmit_handle = GNUNET_CONNECTION_notify_transmit_ready (sock, | ||
1949 | ntohs(tcp_probe_ctx->message.header.size), | ||
1950 | GNUNET_TIME_UNIT_FOREVER_REL, | ||
1951 | ¬ify_send_probe, tcp_probe_ctx); | ||
1952 | |||
1953 | } | ||
1954 | |||
1955 | plugin->server_read_task = | ||
1956 | GNUNET_SCHEDULER_add_read_file (plugin->env->sched, | ||
1957 | GNUNET_TIME_UNIT_FOREVER_REL, | ||
1958 | plugin->server_stdout_handle, &tcp_plugin_server_read, plugin); | ||
1959 | } | ||
1960 | |||
1961 | /** | ||
1962 | * Start the gnunet-nat-server process for users behind NAT. | ||
1963 | * | ||
1964 | * @param plugin the transport plugin | ||
1965 | * | ||
1966 | * @return GNUNET_YES if process was started, GNUNET_SYSERR on error | ||
1967 | */ | ||
1968 | static int | ||
1969 | tcp_transport_start_nat_server(struct Plugin *plugin) | ||
1970 | { | ||
1971 | |||
1972 | plugin->server_stdout = GNUNET_DISK_pipe(GNUNET_YES); | ||
1973 | if (plugin->server_stdout == NULL) | ||
1974 | return GNUNET_SYSERR; | ||
1975 | |||
1976 | #if DEBUG_TCP_NAT | ||
1977 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, | ||
1978 | "tcp", | ||
1979 | "Starting gnunet-nat-server process cmd: %s %s\n", "gnunet-nat-server", plugin->internal_address); | ||
1980 | #endif | ||
1981 | /* Start the server process */ | ||
1982 | plugin->server_pid = GNUNET_OS_start_process(NULL, plugin->server_stdout, "gnunet-nat-server", "gnunet-nat-server", plugin->internal_address, NULL); | ||
1983 | if (plugin->server_pid == GNUNET_SYSERR) | ||
1984 | { | ||
1985 | #if DEBUG_TCP_NAT | ||
1986 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, | ||
1987 | "tcp", | ||
1988 | "Failed to start gnunet-nat-server process\n"); | ||
1989 | #endif | ||
1990 | return GNUNET_SYSERR; | ||
1991 | } | ||
1992 | /* Close the write end of the read pipe */ | ||
1993 | GNUNET_DISK_pipe_close_end(plugin->server_stdout, GNUNET_DISK_PIPE_END_WRITE); | ||
1994 | |||
1995 | plugin->server_stdout_handle = GNUNET_DISK_pipe_handle(plugin->server_stdout, GNUNET_DISK_PIPE_END_READ); | ||
1996 | plugin->server_read_task = | ||
1997 | GNUNET_SCHEDULER_add_read_file (plugin->env->sched, | ||
1998 | GNUNET_TIME_UNIT_FOREVER_REL, | ||
1999 | plugin->server_stdout_handle, &tcp_plugin_server_read, plugin); | ||
2000 | return GNUNET_YES; | ||
2001 | } | ||
2002 | |||
2003 | /** | ||
2004 | * Return the actual path to a file found in the current | ||
2005 | * PATH environment variable. | ||
2006 | * | ||
2007 | * @param binary the name of the file to find | ||
2008 | */ | ||
2009 | static char * | ||
2010 | get_path_from_PATH (char *binary) | ||
2011 | { | ||
2012 | char *path; | ||
2013 | char *pos; | ||
2014 | char *end; | ||
2015 | char *buf; | ||
2016 | const char *p; | ||
2017 | |||
2018 | p = getenv ("PATH"); | ||
2019 | if (p == NULL) | ||
2020 | return NULL; | ||
2021 | path = GNUNET_strdup (p); /* because we write on it */ | ||
2022 | buf = GNUNET_malloc (strlen (path) + 20); | ||
2023 | pos = path; | ||
2024 | |||
2025 | while (NULL != (end = strchr (pos, ':'))) | ||
2026 | { | ||
2027 | *end = '\0'; | ||
2028 | sprintf (buf, "%s/%s", pos, binary); | ||
2029 | if (GNUNET_DISK_file_test (buf) == GNUNET_YES) | ||
2030 | { | ||
2031 | GNUNET_free (path); | ||
2032 | return buf; | ||
2033 | } | ||
2034 | pos = end + 1; | ||
2035 | } | ||
2036 | sprintf (buf, "%s/%s", pos, binary); | ||
2037 | if (GNUNET_DISK_file_test (buf) == GNUNET_YES) | ||
2038 | { | ||
2039 | GNUNET_free (path); | ||
2040 | return buf; | ||
2041 | } | ||
2042 | GNUNET_free (buf); | ||
2043 | GNUNET_free (path); | ||
2044 | return NULL; | ||
2045 | } | ||
2046 | |||
2047 | /** | ||
2048 | * Check whether the suid bit is set on a file. | ||
2049 | * Attempts to find the file using the current | ||
2050 | * PATH environment variable as a search path. | ||
2051 | * | ||
2052 | * @param binary the name of the file to check | ||
2053 | */ | ||
2054 | static int | ||
2055 | check_gnunet_nat_binary(char *binary) | ||
2056 | { | ||
2057 | struct stat statbuf; | ||
2058 | char *p; | ||
2059 | |||
2060 | p = get_path_from_PATH (binary); | ||
2061 | if (p == NULL) | ||
2062 | return GNUNET_NO; | ||
2063 | if (0 != STAT (p, &statbuf)) | ||
2064 | { | ||
2065 | GNUNET_free (p); | ||
2066 | return GNUNET_SYSERR; | ||
2067 | } | ||
2068 | GNUNET_free (p); | ||
2069 | if ( (0 != (statbuf.st_mode & S_ISUID)) && | ||
2070 | (statbuf.st_uid == 0) ) | ||
2071 | return GNUNET_YES; | ||
2072 | return GNUNET_NO; | ||
2073 | } | ||
1514 | 2074 | ||
1515 | /** | 2075 | /** |
1516 | * Entry point for the plugin. | 2076 | * Entry point for the plugin. |
@@ -1528,6 +2088,10 @@ libgnunet_plugin_transport_tcp_init (void *cls) | |||
1528 | unsigned long long aport; | 2088 | unsigned long long aport; |
1529 | unsigned long long bport; | 2089 | unsigned long long bport; |
1530 | unsigned int i; | 2090 | unsigned int i; |
2091 | int behind_nat; | ||
2092 | int allow_nat; | ||
2093 | char *internal_address; | ||
2094 | char *external_address; | ||
1531 | 2095 | ||
1532 | service = GNUNET_SERVICE_start ("transport-tcp", env->sched, env->cfg); | 2096 | service = GNUNET_SERVICE_start ("transport-tcp", env->sched, env->cfg); |
1533 | if (service == NULL) | 2097 | if (service == NULL) |
@@ -1539,6 +2103,73 @@ libgnunet_plugin_transport_tcp_init (void *cls) | |||
1539 | "tcp"); | 2103 | "tcp"); |
1540 | return NULL; | 2104 | return NULL; |
1541 | } | 2105 | } |
2106 | |||
2107 | if (GNUNET_YES == GNUNET_CONFIGURATION_get_value_yesno (env->cfg, | ||
2108 | "transport-tcp", | ||
2109 | "BEHIND_NAT")) | ||
2110 | { | ||
2111 | /* We are behind nat (according to the user) */ | ||
2112 | if (check_gnunet_nat_binary("gnunet-nat-server") == GNUNET_YES) | ||
2113 | behind_nat = GNUNET_YES; | ||
2114 | else | ||
2115 | { | ||
2116 | behind_nat = GNUNET_NO; | ||
2117 | GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING, "tcp", "Configuration specified you are behind a NAT, but gnunet-nat-server is not installed properly (suid bit not set)!\n"); | ||
2118 | } | ||
2119 | } | ||
2120 | else | ||
2121 | behind_nat = GNUNET_NO; /* We are not behind nat! */ | ||
2122 | |||
2123 | if (GNUNET_YES == GNUNET_CONFIGURATION_get_value_yesno (env->cfg, | ||
2124 | "transport-tcp", | ||
2125 | "ALLOW_NAT")) | ||
2126 | { | ||
2127 | if (check_gnunet_nat_binary("gnunet-nat-client") == GNUNET_YES) | ||
2128 | allow_nat = GNUNET_YES; /* We will try to connect to NAT'd peers */ | ||
2129 | else | ||
2130 | { | ||
2131 | allow_nat = GNUNET_NO; | ||
2132 | 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"); | ||
2133 | } | ||
2134 | |||
2135 | } | ||
2136 | else | ||
2137 | allow_nat = GNUNET_NO; /* We don't want to try to help NAT'd peers */ | ||
2138 | |||
2139 | external_address = NULL; | ||
2140 | if (((GNUNET_YES == behind_nat) || (GNUNET_YES == allow_nat)) && (GNUNET_OK != | ||
2141 | GNUNET_CONFIGURATION_get_value_string (env->cfg, | ||
2142 | "transport-tcp", | ||
2143 | "EXTERNAL_ADDRESS", | ||
2144 | &external_address))) | ||
2145 | { | ||
2146 | GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, | ||
2147 | "tcp", | ||
2148 | _ | ||
2149 | ("Require EXTERNAL_ADDRESS for service `%s' in configuration (either BEHIND_NAT or ALLOW_NAT set to YES)!\n"), | ||
2150 | "transport-tcp"); | ||
2151 | GNUNET_SERVICE_stop (service); | ||
2152 | return NULL; | ||
2153 | } | ||
2154 | |||
2155 | internal_address = NULL; | ||
2156 | if ((GNUNET_YES == behind_nat) && (GNUNET_OK != | ||
2157 | GNUNET_CONFIGURATION_get_value_string (env->cfg, | ||
2158 | "transport-tcp", | ||
2159 | "INTERNAL_ADDRESS", | ||
2160 | &internal_address))) | ||
2161 | { | ||
2162 | GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, | ||
2163 | "tcp", | ||
2164 | _ | ||
2165 | ("Require INTERNAL_ADDRESS for service `%s' in configuration!\n"), | ||
2166 | "transport-tcp"); | ||
2167 | GNUNET_SERVICE_stop (service); | ||
2168 | GNUNET_free_non_null(external_address); | ||
2169 | return NULL; | ||
2170 | } | ||
2171 | |||
2172 | |||
1542 | aport = 0; | 2173 | aport = 0; |
1543 | if ((GNUNET_OK != | 2174 | if ((GNUNET_OK != |
1544 | GNUNET_CONFIGURATION_get_value_number (env->cfg, | 2175 | GNUNET_CONFIGURATION_get_value_number (env->cfg, |
@@ -1557,14 +2188,44 @@ libgnunet_plugin_transport_tcp_init (void *cls) | |||
1557 | _ | 2188 | _ |
1558 | ("Require valid port number for service `%s' in configuration!\n"), | 2189 | ("Require valid port number for service `%s' in configuration!\n"), |
1559 | "transport-tcp"); | 2190 | "transport-tcp"); |
2191 | GNUNET_free_non_null(external_address); | ||
2192 | GNUNET_free_non_null(internal_address); | ||
1560 | GNUNET_SERVICE_stop (service); | 2193 | GNUNET_SERVICE_stop (service); |
1561 | return NULL; | 2194 | return NULL; |
1562 | } | 2195 | } |
2196 | |||
2197 | if (behind_nat) | ||
2198 | { | ||
2199 | if (GNUNET_YES != tcp_transport_start_nat_server(plugin)) | ||
2200 | { | ||
2201 | GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, | ||
2202 | "tcp", | ||
2203 | _ | ||
2204 | ("Failed to start %s required for NAT in %s!\n"), | ||
2205 | "gnunet-nat-server" | ||
2206 | "transport-tcp"); | ||
2207 | GNUNET_free_non_null(external_address); | ||
2208 | GNUNET_free_non_null(internal_address); | ||
2209 | GNUNET_SERVICE_stop (service); | ||
2210 | return NULL; | ||
2211 | } | ||
2212 | } | ||
2213 | |||
2214 | if (allow_nat) | ||
2215 | { | ||
2216 | plugin->nat_wait_conns = GNUNET_CONTAINER_multihashmap_create(100); | ||
2217 | GNUNET_assert(plugin->nat_wait_conns != NULL); | ||
2218 | } | ||
2219 | |||
1563 | if (aport == 0) | 2220 | if (aport == 0) |
1564 | aport = bport; | 2221 | aport = bport; |
1565 | plugin = GNUNET_malloc (sizeof (struct Plugin)); | 2222 | plugin = GNUNET_malloc (sizeof (struct Plugin)); |
1566 | plugin->open_port = bport; | 2223 | plugin->open_port = bport; |
1567 | plugin->adv_port = aport; | 2224 | plugin->adv_port = aport; |
2225 | plugin->external_address = external_address; | ||
2226 | plugin->internal_address = internal_address; | ||
2227 | plugin->behind_nat = behind_nat; | ||
2228 | plugin->allow_nat = allow_nat; | ||
1568 | plugin->env = env; | 2229 | plugin->env = env; |
1569 | plugin->lsock = NULL; | 2230 | plugin->lsock = NULL; |
1570 | api = GNUNET_malloc (sizeof (struct GNUNET_TRANSPORT_PluginFunctions)); | 2231 | 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 f36f587ad..10bbf2972 100644 --- a/src/transport/plugin_transport_udp.c +++ b/src/transport/plugin_transport_udp.c | |||
@@ -1296,15 +1296,14 @@ udp_transport_server_start (void *cls) | |||
1296 | socklen_t addrlen; | 1296 | socklen_t addrlen; |
1297 | int sockets_created; | 1297 | int sockets_created; |
1298 | 1298 | ||
1299 | /* Pipe to read from started processes stdout (on read end) */ | ||
1300 | plugin->server_stdout = GNUNET_DISK_pipe(GNUNET_YES); | ||
1301 | |||
1302 | sockets_created = 0; | 1299 | sockets_created = 0; |
1303 | if (plugin->server_stdout == NULL) | ||
1304 | return sockets_created; | ||
1305 | 1300 | ||
1306 | if (plugin->behind_nat == GNUNET_YES) | 1301 | if (plugin->behind_nat == GNUNET_YES) |
1307 | { | 1302 | { |
1303 | /* Pipe to read from started processes stdout (on read end) */ | ||
1304 | plugin->server_stdout = GNUNET_DISK_pipe(GNUNET_YES); | ||
1305 | if (plugin->server_stdout == NULL) | ||
1306 | return sockets_created; | ||
1308 | #if DEBUG_UDP_NAT | 1307 | #if DEBUG_UDP_NAT |
1309 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, | 1308 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, |
1310 | "udp", | 1309 | "udp", |
@@ -1410,32 +1409,6 @@ udp_transport_server_start (void *cls) | |||
1410 | 1409 | ||
1411 | 1410 | ||
1412 | /** | 1411 | /** |
1413 | * Check if the given port is plausible (must be either | ||
1414 | * our listen port or our advertised port). If it is | ||
1415 | * neither, we return one of these two ports at random. | ||
1416 | * | ||
1417 | * @return either in_port or a more plausible port | ||
1418 | */ | ||
1419 | static uint16_t | ||
1420 | check_port (struct Plugin *plugin, uint16_t in_port) | ||
1421 | { | ||
1422 | |||
1423 | /* FIXME: remember what ports we are using to better respond to this */ | ||
1424 | return in_port; | ||
1425 | /* | ||
1426 | for (i = plugin->starting_port; i < plugin->num_ports + plugin->starting_port; i++) | ||
1427 | { | ||
1428 | if (in_port == i) | ||
1429 | return in_port; | ||
1430 | } | ||
1431 | |||
1432 | return GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, | ||
1433 | plugin->num_ports) + plugin->starting_port; | ||
1434 | */ | ||
1435 | } | ||
1436 | |||
1437 | |||
1438 | /** | ||
1439 | * Another peer has suggested an address for this peer and transport | 1412 | * Another peer has suggested an address for this peer and transport |
1440 | * plugin. Check that this could be a valid address. This function | 1413 | * plugin. Check that this could be a valid address. This function |
1441 | * is not expected to 'validate' the address in the sense of trying to | 1414 | * is not expected to 'validate' the address in the sense of trying to |
@@ -1468,12 +1441,12 @@ udp_check_address (void *cls, void *addr, size_t addrlen) | |||
1468 | if (addrlen == sizeof (struct sockaddr_in)) | 1441 | if (addrlen == sizeof (struct sockaddr_in)) |
1469 | { | 1442 | { |
1470 | v4 = (struct sockaddr_in *) buf; | 1443 | v4 = (struct sockaddr_in *) buf; |
1471 | v4->sin_port = htons (check_port (plugin, ntohs (v4->sin_port))); | 1444 | v4->sin_port = htons (plugin->port); |
1472 | } | 1445 | } |
1473 | else | 1446 | else |
1474 | { | 1447 | { |
1475 | v6 = (struct sockaddr_in6 *) buf; | 1448 | v6 = (struct sockaddr_in6 *) buf; |
1476 | v6->sin6_port = htons (check_port (plugin, ntohs (v6->sin6_port))); | 1449 | v6->sin6_port = htons (plugin->port); |
1477 | } | 1450 | } |
1478 | 1451 | ||
1479 | #if DEBUG_UDP_NAT | 1452 | #if DEBUG_UDP_NAT |
diff --git a/src/transport/test_transport_api_tcp_peer1.conf b/src/transport/test_transport_api_tcp_peer1.conf index f5bdc2063..e3778cd8e 100644 --- a/src/transport/test_transport_api_tcp_peer1.conf +++ b/src/transport/test_transport_api_tcp_peer1.conf | |||
@@ -39,6 +39,7 @@ ACCEPT_FROM6 = ::1; | |||
39 | ACCEPT_FROM = 127.0.0.1; | 39 | ACCEPT_FROM = 127.0.0.1; |
40 | NEIGHBOUR_LIMIT = 50 | 40 | NEIGHBOUR_LIMIT = 50 |
41 | BINARY = gnunet-service-transport | 41 | BINARY = gnunet-service-transport |
42 | #BINARY = /home/mrwiggles/documents/research/gnunet/gnunet-ng/src/transport/.libs/gnunet-service-transport | ||
42 | CONFIG = $DEFAULTCONFIG | 43 | CONFIG = $DEFAULTCONFIG |
43 | HOME = $SERVICEHOME | 44 | HOME = $SERVICEHOME |
44 | HOSTNAME = localhost | 45 | HOSTNAME = localhost |
diff --git a/src/transport/test_transport_api_tcp_peer2.conf b/src/transport/test_transport_api_tcp_peer2.conf index f2c22e336..6362ebd27 100644 --- a/src/transport/test_transport_api_tcp_peer2.conf +++ b/src/transport/test_transport_api_tcp_peer2.conf | |||
@@ -33,17 +33,18 @@ MINIMUM-FRIENDS = 0 | |||
33 | [transport] | 33 | [transport] |
34 | PLUGINS = tcp | 34 | PLUGINS = tcp |
35 | DEBUG = NO | 35 | DEBUG = NO |
36 | # PREFIX = | 36 | #DEBUG = YES |
37 | ACCEPT_FROM6 = ::1; | 37 | ACCEPT_FROM6 = ::1; |
38 | ACCEPT_FROM = 127.0.0.1; | 38 | ACCEPT_FROM = 127.0.0.1; |
39 | NEIGHBOUR_LIMIT = 50 | 39 | NEIGHBOUR_LIMIT = 50 |
40 | #BINARY = /home/mrwiggles/documents/research/gnunet/gnunet-ng/src/transport/.libs/gnunet-service-transport | ||
40 | BINARY = gnunet-service-transport | 41 | BINARY = gnunet-service-transport |
41 | CONFIG = $DEFAULTCONFIG | 42 | CONFIG = $DEFAULTCONFIG |
42 | HOME = $SERVICEHOME | 43 | HOME = $SERVICEHOME |
43 | HOSTNAME = localhost | 44 | HOSTNAME = localhost |
44 | PORT = 22365 | 45 | PORT = 22365 |
45 | UNIXPATH = /tmp/gnunet-p2-service-transport.sock | 46 | UNIXPATH = /tmp/gnunet-p2-service-transport.sock |
46 | #PREFIX = xterm -T transport1 -e gdb --command=cmd --args | 47 | #PREFIX = xterm -T transport2 -e gdb --command=cmd --args |
47 | #PREFIX = valgrind --leak-check=full | 48 | #PREFIX = valgrind --leak-check=full |
48 | 49 | ||
49 | [peerinfo] | 50 | [peerinfo] |